diff options
Diffstat (limited to 'sys/dev/bnxt')
35 files changed, 48666 insertions, 5442 deletions
diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h deleted file mode 100644 index 0547bae91e09..000000000000 --- a/sys/dev/bnxt/bnxt.h +++ /dev/null @@ -1,848 +0,0 @@ -/*- - * Broadcom NetXtreme-C/E network driver. - * - * Copyright (c) 2016 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 <sys/cdefs.h> -#ifndef _BNXT_H -#define _BNXT_H - -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/taskqueue.h> -#include <sys/bitstring.h> - -#include <machine/bus.h> - -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_var.h> -#include <net/iflib.h> - -#include "hsi_struct_def.h" - -/* PCI IDs */ -#define BROADCOM_VENDOR_ID 0x14E4 - -#define BCM57301 0x16c8 -#define BCM57302 0x16c9 -#define BCM57304 0x16ca -#define BCM57311 0x16ce -#define BCM57312 0x16cf -#define BCM57314 0x16df -#define BCM57402 0x16d0 -#define BCM57402_NPAR 0x16d4 -#define BCM57404 0x16d1 -#define BCM57404_NPAR 0x16e7 -#define BCM57406 0x16d2 -#define BCM57406_NPAR 0x16e8 -#define BCM57407 0x16d5 -#define BCM57407_NPAR 0x16ea -#define BCM57407_SFP 0x16e9 -#define BCM57412 0x16d6 -#define BCM57412_NPAR1 0x16de -#define BCM57412_NPAR2 0x16eb -#define BCM57414 0x16d7 -#define BCM57414_NPAR1 0x16ec -#define BCM57414_NPAR2 0x16ed -#define BCM57416 0x16d8 -#define BCM57416_NPAR1 0x16ee -#define BCM57416_NPAR2 0x16ef -#define BCM57416_SFP 0x16e3 -#define BCM57417 0x16d9 -#define BCM57417_NPAR1 0x16c0 -#define BCM57417_NPAR2 0x16cc -#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 -#define NETXTREME_E_VF1 0x16c1 -#define NETXTREME_E_VF2 0x16d3 -#define NETXTREME_E_VF3 0x16dc - -/* 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) -#define BNXT_MAX_TXD ((INT32_MAX >> 1) + 1) - -#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \ - CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \ - CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP) - -#define BNXT_MAX_MTU 9600 - -#define BNXT_RSS_HASH_TYPE_TCPV4 0 -#define BNXT_RSS_HASH_TYPE_UDPV4 1 -#define BNXT_RSS_HASH_TYPE_IPV4 2 -#define BNXT_RSS_HASH_TYPE_TCPV6 3 -#define BNXT_RSS_HASH_TYPE_UDPV6 4 -#define BNXT_RSS_HASH_TYPE_IPV6 5 -#define BNXT_GET_RSS_PROFILE_ID(rss_hash_type) ((rss_hash_type >> 1) & 0x1F) - -#define BNXT_NO_MORE_WOL_FILTERS 0xFFFF -#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); \ -} while (0) - -#define RING_NEXT(ring, idx) (__predict_false(idx + 1 == (ring)->ring_size) ? \ - 0 : idx + 1) - -#define CMPL_PREFETCH_NEXT(cpr, idx) \ - __builtin_prefetch(&((struct cmpl_base *)(cpr)->ring.vaddr)[((idx) +\ - (CACHE_LINE_SIZE / sizeof(struct cmpl_base))) & \ - ((cpr)->ring.ring_size - 1)]) - -/* Lock macros */ -#define BNXT_HWRM_LOCK_INIT(_softc, _name) \ - mtx_init(&(_softc)->hwrm_lock, _name, "BNXT HWRM Lock", MTX_DEF) -#define BNXT_HWRM_LOCK(_softc) mtx_lock(&(_softc)->hwrm_lock) -#define BNXT_HWRM_UNLOCK(_softc) mtx_unlock(&(_softc)->hwrm_lock) -#define BNXT_HWRM_LOCK_DESTROY(_softc) mtx_destroy(&(_softc)->hwrm_lock) -#define BNXT_HWRM_LOCK_ASSERT(_softc) mtx_assert(&(_softc)->hwrm_lock, \ - MA_OWNED) -#define BNXT_IS_FLOW_CTRL_CHANGED(link_info) \ - ((link_info->last_flow_ctrl.tx != link_info->flow_ctrl.tx) || \ - (link_info->last_flow_ctrl.rx != link_info->flow_ctrl.rx) || \ - (link_info->last_flow_ctrl.autoneg != link_info->flow_ctrl.autoneg)) - -/* Chip info */ -#define BNXT_TSO_SIZE UINT16_MAX - -#define min_t(type, x, y) ({ \ - type __min1 = (x); \ - type __min2 = (y); \ - __min1 < __min2 ? __min1 : __min2; }) - -#define max_t(type, x, y) ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1 : __max2; }) - -#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) - -#define BNXT_IFMEDIA_ADD(supported, fw_speed, ifm_speed) do { \ - if ((supported) & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_ ## fw_speed) \ - ifmedia_add(softc->media, IFM_ETHER | (ifm_speed), 0, NULL); \ -} while(0) - -#define BNXT_MIN_FRAME_SIZE 52 /* Frames must be padded to this size for some A0 chips */ - -extern const char bnxt_driver_version[]; -typedef void (*bnxt_doorbell_tx)(void *, uint16_t idx); -typedef void (*bnxt_doorbell_rx)(void *, uint16_t idx); -typedef void (*bnxt_doorbell_rx_cq)(void *, bool); -typedef void (*bnxt_doorbell_tx_cq)(void *, bool); -typedef void (*bnxt_doorbell_nq)(void *, bool); - -typedef struct bnxt_doorbell_ops { - bnxt_doorbell_tx bnxt_db_tx; - bnxt_doorbell_rx bnxt_db_rx; - bnxt_doorbell_rx_cq bnxt_db_rx_cq; - bnxt_doorbell_tx_cq bnxt_db_tx_cq; - bnxt_doorbell_nq bnxt_db_nq; -} bnxt_dooorbell_ops_t; -/* NVRAM access */ -enum bnxt_nvm_directory_type { - BNX_DIR_TYPE_UNUSED = 0, - BNX_DIR_TYPE_PKG_LOG = 1, - BNX_DIR_TYPE_UPDATE = 2, - BNX_DIR_TYPE_CHIMP_PATCH = 3, - BNX_DIR_TYPE_BOOTCODE = 4, - BNX_DIR_TYPE_VPD = 5, - BNX_DIR_TYPE_EXP_ROM_MBA = 6, - BNX_DIR_TYPE_AVS = 7, - BNX_DIR_TYPE_PCIE = 8, - BNX_DIR_TYPE_PORT_MACRO = 9, - BNX_DIR_TYPE_APE_FW = 10, - BNX_DIR_TYPE_APE_PATCH = 11, - BNX_DIR_TYPE_KONG_FW = 12, - BNX_DIR_TYPE_KONG_PATCH = 13, - BNX_DIR_TYPE_BONO_FW = 14, - BNX_DIR_TYPE_BONO_PATCH = 15, - BNX_DIR_TYPE_TANG_FW = 16, - BNX_DIR_TYPE_TANG_PATCH = 17, - BNX_DIR_TYPE_BOOTCODE_2 = 18, - BNX_DIR_TYPE_CCM = 19, - BNX_DIR_TYPE_PCI_CFG = 20, - BNX_DIR_TYPE_TSCF_UCODE = 21, - BNX_DIR_TYPE_ISCSI_BOOT = 22, - BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, - BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, - BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26, - BNX_DIR_TYPE_EXT_PHY = 27, - BNX_DIR_TYPE_SHARED_CFG = 40, - BNX_DIR_TYPE_PORT_CFG = 41, - BNX_DIR_TYPE_FUNC_CFG = 42, - BNX_DIR_TYPE_MGMT_CFG = 48, - BNX_DIR_TYPE_MGMT_DATA = 49, - BNX_DIR_TYPE_MGMT_WEB_DATA = 50, - BNX_DIR_TYPE_MGMT_WEB_META = 51, - BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, - BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 -}; - -enum bnxnvm_pkglog_field_index { - BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, - BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, - BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, - BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, - BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, - BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, - BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 -}; - -#define BNX_DIR_ORDINAL_FIRST 0 -#define BNX_DIR_EXT_NONE 0 - -struct bnxt_bar_info { - struct resource *res; - bus_space_tag_t tag; - bus_space_handle_t handle; - bus_size_t size; - int rid; -}; - -struct bnxt_flow_ctrl { - bool rx; - bool tx; - bool autoneg; -}; - -struct bnxt_link_info { - uint8_t media_type; - uint8_t transceiver; - uint8_t phy_addr; - uint8_t phy_link_status; - uint8_t wire_speed; - uint8_t loop_back; - uint8_t link_up; - uint8_t last_link_up; - uint8_t duplex; - uint8_t last_duplex; - uint8_t last_phy_type; - struct bnxt_flow_ctrl flow_ctrl; - struct bnxt_flow_ctrl last_flow_ctrl; - uint8_t duplex_setting; - uint8_t auto_mode; -#define PHY_VER_LEN 3 - uint8_t phy_ver[PHY_VER_LEN]; - uint8_t phy_type; -#define BNXT_PHY_STATE_ENABLED 0 -#define BNXT_PHY_STATE_DISABLED 1 - uint8_t phy_state; - - uint16_t link_speed; - uint16_t support_speeds; - uint16_t support_pam4_speeds; - uint16_t auto_link_speeds; - uint16_t auto_pam4_link_speeds; - uint16_t force_link_speed; - uint16_t force_pam4_link_speed; - bool force_pam4_speed_set_by_user; - - uint16_t advertising; - uint16_t advertising_pam4; - - uint32_t preemphasis; - uint16_t support_auto_speeds; - uint16_t support_force_speeds; - uint16_t support_pam4_auto_speeds; - uint16_t support_pam4_force_speeds; -#define BNXT_SIG_MODE_NRZ HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_NRZ -#define BNXT_SIG_MODE_PAM4 HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4 - uint8_t req_signal_mode; - - uint8_t active_fec_sig_mode; - uint8_t sig_mode; - - /* copy of requested setting */ - uint8_t autoneg; -#define BNXT_AUTONEG_SPEED 1 -#define BNXT_AUTONEG_FLOW_CTRL 2 - uint8_t req_duplex; - uint16_t req_link_speed; - uint8_t module_status; - struct hwrm_port_phy_qcfg_output phy_qcfg_resp; -}; - -enum bnxt_phy_type { - BNXT_MEDIA_CR = 0, - BNXT_MEDIA_LR, - BNXT_MEDIA_SR, - BNXT_MEDIA_KR, - BNXT_MEDIA_END -}; - -enum bnxt_cp_type { - BNXT_DEFAULT, - BNXT_TX, - BNXT_RX, - BNXT_SHARED -}; - -struct bnxt_cos_queue { - uint8_t id; - uint8_t profile; -}; - -struct bnxt_func_info { - uint32_t fw_fid; - uint8_t mac_addr[ETHER_ADDR_LEN]; - uint16_t max_rsscos_ctxs; - uint16_t max_cp_rings; - uint16_t max_tx_rings; - uint16_t max_rx_rings; - uint16_t max_hw_ring_grps; - uint16_t max_irqs; - uint16_t max_l2_ctxs; - uint16_t max_vnics; - uint16_t max_stat_ctxs; -}; - -struct bnxt_pf_info { -#define BNXT_FIRST_PF_FID 1 -#define BNXT_FIRST_VF_FID 128 - uint8_t port_id; - uint32_t first_vf_id; - uint16_t active_vfs; - uint16_t max_vfs; - uint32_t max_encap_records; - uint32_t max_decap_records; - uint32_t max_tx_em_flows; - uint32_t max_tx_wm_flows; - uint32_t max_rx_em_flows; - uint32_t max_rx_wm_flows; - unsigned long *vf_event_bmap; - uint16_t hwrm_cmd_req_pages; - void *hwrm_cmd_req_addr[4]; - bus_addr_t hwrm_cmd_req_dma_addr[4]; -}; - -struct bnxt_vf_info { - uint16_t fw_fid; - uint8_t mac_addr[ETHER_ADDR_LEN]; - uint16_t max_rsscos_ctxs; - uint16_t max_cp_rings; - uint16_t max_tx_rings; - uint16_t max_rx_rings; - uint16_t max_hw_ring_grps; - uint16_t max_l2_ctxs; - uint16_t max_irqs; - uint16_t max_vnics; - uint16_t max_stat_ctxs; - uint32_t vlan; -#define BNXT_VF_QOS 0x1 -#define BNXT_VF_SPOOFCHK 0x2 -#define BNXT_VF_LINK_FORCED 0x4 -#define BNXT_VF_LINK_UP 0x8 - uint32_t flags; - uint32_t func_flags; /* func cfg flags */ - uint32_t min_tx_rate; - uint32_t max_tx_rate; - void *hwrm_cmd_req_addr; - bus_addr_t hwrm_cmd_req_dma_addr; -}; - -#define BNXT_PF(softc) (!((softc)->flags & BNXT_FLAG_VF)) -#define BNXT_VF(softc) ((softc)->flags & BNXT_FLAG_VF) - -struct bnxt_vlan_tag { - SLIST_ENTRY(bnxt_vlan_tag) next; - uint64_t filter_id; - uint16_t tag; -}; - -struct bnxt_vnic_info { - uint16_t id; - uint16_t def_ring_grp; - uint16_t cos_rule; - uint16_t lb_rule; - uint16_t mru; - - uint32_t rx_mask; - struct iflib_dma_info mc_list; - int mc_list_count; -#define BNXT_MAX_MC_ADDRS 16 - - uint32_t flags; -#define BNXT_VNIC_FLAG_DEFAULT 0x01 -#define BNXT_VNIC_FLAG_BD_STALL 0x02 -#define BNXT_VNIC_FLAG_VLAN_STRIP 0x04 - - uint64_t filter_id; - - uint16_t rss_id; - uint32_t rss_hash_type; - uint8_t rss_hash_key[HW_HASH_KEY_SIZE]; - struct iflib_dma_info rss_hash_key_tbl; - struct iflib_dma_info rss_grp_tbl; - SLIST_HEAD(vlan_head, bnxt_vlan_tag) vlan_tags; - struct iflib_dma_info vlan_tag_list; -}; - -struct bnxt_grp_info { - uint16_t stats_ctx; - uint16_t grp_id; - uint16_t rx_ring_id; - uint16_t cp_ring_id; - uint16_t ag_ring_id; -}; - -struct bnxt_ring { - uint64_t paddr; - vm_offset_t doorbell; - caddr_t vaddr; - struct bnxt_softc *softc; - 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; -}; - -struct bnxt_cp_ring { - struct bnxt_ring ring; - struct if_irq irq; - uint32_t cons; - bool v_bit; /* Value of valid bit */ - struct ctx_hw_stats *stats; - uint32_t stats_ctx_id; - uint32_t last_idx; /* Used by RX rings only - * set to the last read pidx - */ - uint64_t int_count; -}; - -struct bnxt_full_tpa_start { - struct rx_tpa_start_cmpl low; - struct rx_tpa_start_cmpl_hi high; -}; - -/* All the version information for the part */ -#define BNXT_VERSTR_SIZE (3*3+2+1) /* ie: "255.255.255\0" */ -#define BNXT_NAME_SIZE 17 -#define FW_VER_STR_LEN 32 -#define BC_HWRM_STR_LEN 21 -struct bnxt_ver_info { - uint8_t hwrm_if_major; - uint8_t hwrm_if_minor; - 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 fw_ver_str[FW_VER_STR_LEN]; - char phy_ver[BNXT_VERSTR_SIZE]; - char pkg_ver[64]; - - char hwrm_fw_name[BNXT_NAME_SIZE]; - char mgmt_fw_name[BNXT_NAME_SIZE]; - char netctrl_fw_name[BNXT_NAME_SIZE]; - char roce_fw_name[BNXT_NAME_SIZE]; - char phy_vendor[BNXT_NAME_SIZE]; - char phy_partnumber[BNXT_NAME_SIZE]; - - uint16_t chip_num; - uint8_t chip_rev; - uint8_t chip_metal; - uint8_t chip_bond_id; - uint8_t chip_type; - - uint8_t hwrm_min_major; - uint8_t hwrm_min_minor; - uint8_t hwrm_min_update; - - struct sysctl_ctx_list ver_ctx; - struct sysctl_oid *ver_oid; -}; - -struct bnxt_nvram_info { - uint16_t mfg_id; - uint16_t device_id; - uint32_t sector_size; - uint32_t size; - uint32_t reserved_size; - uint32_t available_size; - - struct sysctl_ctx_list nvm_ctx; - struct sysctl_oid *nvm_oid; -}; - -struct bnxt_func_qcfg { - uint16_t alloc_completion_rings; - uint16_t alloc_tx_rings; - uint16_t alloc_rx_rings; - uint16_t alloc_vnics; -}; - -struct bnxt_hw_lro { - uint16_t enable; - uint16_t is_mode_gro; - uint16_t max_agg_segs; - uint16_t max_aggs; - 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_list { - SLIST_ENTRY(bnxt_softc_list) next; - struct bnxt_softc *softc; -}; - -struct bnxt_softc { - device_t dev; - if_ctx_t ctx; - if_softc_ctx_t scctx; - if_shared_ctx_t sctx; - uint32_t domain; - uint32_t bus; - uint32_t slot; - uint32_t function; - uint32_t dev_fn; - struct ifmedia *media; - struct bnxt_ctx_mem_info *ctx_mem; - struct bnxt_hw_resc hw_resc; - struct bnxt_softc_list list; - - struct bnxt_bar_info hwrm_bar; - struct bnxt_bar_info doorbell_bar; - struct bnxt_link_info link_info; -#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_FW_CAP_NEW_RM 0x0010 -#define BNXT_FLAG_CHIP_P5 0x0020 -#define BNXT_FLAG_TPA 0x0040 -#define BNXT_FLAG_FW_CAP_EXT_STATS 0x0080 - 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; - - struct bnxt_func_info func; - struct bnxt_func_qcfg fn_qcfg; - struct bnxt_pf_info pf; - struct bnxt_vf_info vf; - - uint16_t hwrm_cmd_seq; - uint32_t hwrm_cmd_timeo; /* milliseconds */ - struct iflib_dma_info hwrm_cmd_resp; - struct iflib_dma_info hwrm_short_cmd_req_addr; - /* Interrupt info for HWRM */ - 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_COS_QUEUE 8 - uint8_t max_tc; - 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; - struct iflib_dma_info hw_tx_port_stats; - struct rx_port_stats *rx_port_stats; - struct tx_port_stats *tx_port_stats; - - struct iflib_dma_info hw_tx_port_stats_ext; - struct iflib_dma_info hw_rx_port_stats_ext; - struct tx_port_stats_ext *tx_port_stats_ext; - struct rx_port_stats_ext *rx_port_stats_ext; - - 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[BNXT_MAX_NUM_QUEUES]; - int ntxqsets; - - struct bnxt_vnic_info vnic_info; - struct bnxt_ring *ag_rings; - struct bnxt_ring *rx_rings; - struct bnxt_cp_ring *rx_cp_rings; - struct bnxt_grp_info *grp_info; - struct iflib_dma_info rx_stats[BNXT_MAX_NUM_QUEUES]; - int nrxqsets; - uint16_t rx_buf_size; - - 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; - - struct sysctl_ctx_list hw_stats; - struct sysctl_oid *hw_stats_oid; - struct sysctl_ctx_list hw_lro_ctx; - struct sysctl_oid *hw_lro_oid; - struct sysctl_ctx_list flow_ctrl_ctx; - struct sysctl_oid *flow_ctrl_oid; - - struct bnxt_ver_info *ver_info; - struct bnxt_nvram_info *nvm_info; - bool wol; - bool is_dev_init; - struct bnxt_hw_lro hw_lro; - uint8_t wol_filter_id; - uint16_t rx_coal_usecs; - uint16_t rx_coal_usecs_irq; - uint16_t rx_coal_frames; - uint16_t rx_coal_frames_irq; - uint16_t tx_coal_usecs; - uint16_t tx_coal_usecs_irq; - uint16_t tx_coal_frames; - uint16_t tx_coal_frames_irq; - -#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2) -#define BNXT_DEF_STATS_COAL_TICKS 1000000 -#define BNXT_MIN_STATS_COAL_TICKS 250000 -#define BNXT_MAX_STATS_COAL_TICKS 1000000 - -}; - -struct bnxt_filter_info { - STAILQ_ENTRY(bnxt_filter_info) next; - uint64_t fw_l2_filter_id; -#define INVALID_MAC_INDEX ((uint16_t)-1) - uint16_t mac_index; - - /* Filter Characteristics */ - uint32_t flags; - uint32_t enables; - uint8_t l2_addr[ETHER_ADDR_LEN]; - uint8_t l2_addr_mask[ETHER_ADDR_LEN]; - uint16_t l2_ovlan; - uint16_t l2_ovlan_mask; - uint16_t l2_ivlan; - uint16_t l2_ivlan_mask; - uint8_t t_l2_addr[ETHER_ADDR_LEN]; - uint8_t t_l2_addr_mask[ETHER_ADDR_LEN]; - uint16_t t_l2_ovlan; - uint16_t t_l2_ovlan_mask; - uint16_t t_l2_ivlan; - uint16_t t_l2_ivlan_mask; - uint8_t tunnel_type; - uint16_t mirror_vnic_id; - uint32_t vni; - uint8_t pri_hint; - uint64_t l2_filter_id_hint; -}; - -#define I2C_DEV_ADDR_A0 0xa0 -#define BNXT_MAX_PHY_I2C_RESP_SIZE 64 - -/* Function declarations */ -void bnxt_report_link(struct bnxt_softc *softc); -bool bnxt_check_hwrm_version(struct bnxt_softc *softc); -struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, char *name); -int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *bp, uint16_t i2c_addr, - uint16_t page_number, uint8_t bank, bool bank_sel_en, uint16_t start_addr, - uint16_t data_length, uint8_t *buf); -uint8_t get_phy_type(struct bnxt_softc *softc); - -#endif /* _BNXT_H */ diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h new file mode 100644 index 000000000000..0ba7b5723b91 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -0,0 +1,1390 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 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 <sys/cdefs.h> +#ifndef _BNXT_H +#define _BNXT_H + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/taskqueue.h> +#include <sys/bitstring.h> + +#include <machine/bus.h> + +#include <net/ethernet.h> +#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 + +#define BCM57301 0x16c8 +#define BCM57302 0x16c9 +#define BCM57304 0x16ca +#define BCM57311 0x16ce +#define BCM57312 0x16cf +#define BCM57314 0x16df +#define BCM57402 0x16d0 +#define BCM57402_NPAR 0x16d4 +#define BCM57404 0x16d1 +#define BCM57404_NPAR 0x16e7 +#define BCM57406 0x16d2 +#define BCM57406_NPAR 0x16e8 +#define BCM57407 0x16d5 +#define BCM57407_NPAR 0x16ea +#define BCM57407_SFP 0x16e9 +#define BCM57412 0x16d6 +#define BCM57412_NPAR1 0x16de +#define BCM57412_NPAR2 0x16eb +#define BCM57414 0x16d7 +#define BCM57414_NPAR1 0x16ec +#define BCM57414_NPAR2 0x16ed +#define BCM57416 0x16d8 +#define BCM57416_NPAR1 0x16ee +#define BCM57416_NPAR2 0x16ef +#define BCM57416_SFP 0x16e3 +#define BCM57417 0x16d9 +#define BCM57417_NPAR1 0x16c0 +#define BCM57417_NPAR2 0x16cc +#define BCM57417_SFP 0x16e2 +#define BCM57454 0x1614 +#define BCM58700 0x16cd +#define BCM57508 0x1750 +#define BCM57504 0x1751 +#define BCM57504_NPAR 0x1801 +#define BCM57502 0x1752 +#define BCM57608 0x1760 +#define BCM57604 0x1761 +#define BCM57602 0x1762 +#define BCM57601 0x1763 +#define NETXTREME_C_VF1 0x16cb +#define NETXTREME_C_VF2 0x16e1 +#define NETXTREME_C_VF3 0x16e5 +#define NETXTREME_E_VF1 0x16c1 +#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 EVENT_DATA1_RESET_NOTIFY_FW_ACTIVATION(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) ==\ + HWRM_ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION) + +#define EVENT_DATA2_RESET_NOTIFY_FW_STATUS_CODE(data2) \ + ((data2) & \ + HWRM_ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA2_FW_STATUS_CODE_MASK) + +#define EVENT_DATA1_RECOVERY_ENABLED(data1) \ + !!((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED) + +#define EVENT_DATA1_RECOVERY_MASTER_FUNC(data1) \ + !!((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASTER_FUNC) + +#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) +#define BNXT_MAX_TXD ((INT32_MAX >> 1) + 1) + +#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \ + CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \ + CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP) + +#define BNXT_MAX_MTU 9600 + +#define BNXT_RSS_HASH_TYPE_TCPV4 0 +#define BNXT_RSS_HASH_TYPE_UDPV4 1 +#define BNXT_RSS_HASH_TYPE_IPV4 2 +#define BNXT_RSS_HASH_TYPE_TCPV6 3 +#define BNXT_RSS_HASH_TYPE_UDPV6 4 +#define BNXT_RSS_HASH_TYPE_IPV6 5 +#define BNXT_GET_RSS_PROFILE_ID(rss_hash_type) ((rss_hash_type >> 1) & 0x1F) + +#define BNXT_NO_MORE_WOL_FILTERS 0xFFFF +#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_EPOCH_MASK 0x01000000UL +#define DBR_EPOCH_SFT 24 +#define DBR_TOGGLE_MASK 0x06000000UL +#define DBR_TOGGLE_SFT 25 +#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_NQ_MASK (0xeULL << 60) +#define DBR_TYPE_NULL (0xfULL << 60) + +#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) ((sc->flags & BNXT_FLAG_CHIP_P5)) + +/* Chip class phase 7 */ +#define BNXT_CHIP_P7(sc) ((sc->flags & BNXT_FLAG_CHIP_P7)) + +/* Chip class phase 5 plus */ +#define BNXT_CHIP_P5_PLUS(sc) \ + (BNXT_CHIP_P5(sc) || BNXT_CHIP_P7(sc)) + +#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) ) + +#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); \ +} while (0) + +#define RING_NEXT(ring, idx) (__predict_false(idx + 1 == (ring)->ring_size) ? \ + 0 : idx + 1) + +#define CMPL_PREFETCH_NEXT(cpr, idx) \ + __builtin_prefetch(&((struct cmpl_base *)(cpr)->ring.vaddr)[((idx) +\ + (CACHE_LINE_SIZE / sizeof(struct cmpl_base))) & \ + ((cpr)->ring.ring_size - 1)]) + +/* Lock macros */ +#define BNXT_HWRM_LOCK_INIT(_softc, _name) \ + mtx_init(&(_softc)->hwrm_lock, _name, "BNXT HWRM Lock", MTX_DEF) +#define BNXT_HWRM_LOCK(_softc) mtx_lock(&(_softc)->hwrm_lock) +#define BNXT_HWRM_UNLOCK(_softc) mtx_unlock(&(_softc)->hwrm_lock) +#define BNXT_HWRM_LOCK_DESTROY(_softc) mtx_destroy(&(_softc)->hwrm_lock) +#define BNXT_HWRM_LOCK_ASSERT(_softc) mtx_assert(&(_softc)->hwrm_lock, \ + MA_OWNED) +#define BNXT_IS_FLOW_CTRL_CHANGED(link_info) \ + ((link_info->last_flow_ctrl.tx != link_info->flow_ctrl.tx) || \ + (link_info->last_flow_ctrl.rx != link_info->flow_ctrl.rx) || \ + (link_info->last_flow_ctrl.autoneg != link_info->flow_ctrl.autoneg)) + +/* Chip info */ +#define BNXT_TSO_SIZE UINT16_MAX + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1 : __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1 : __max2; }) + +#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) + +#define BNXT_IFMEDIA_ADD(supported, fw_speed, ifm_speed) do { \ + if ((supported) & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_ ## fw_speed) \ + ifmedia_add(softc->media, IFM_ETHER | (ifm_speed), 0, NULL); \ +} while(0) + +#define BNXT_MIN_FRAME_SIZE 52 /* Frames must be padded to this size for some A0 chips */ + +#define BNXT_RX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct rx_port_stats_ext, counter) / 8) + +#define BNXT_RX_STATS_EXT_NUM_LEGACY \ + BNXT_RX_STATS_EXT_OFFSET(rx_fec_corrected_blocks) + +#define BNXT_TX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct tx_port_stats_ext, counter) / 8) + +extern const char bnxt_driver_version[]; +typedef void (*bnxt_doorbell_tx)(void *, uint16_t idx); +typedef void (*bnxt_doorbell_rx)(void *, uint16_t idx); +typedef void (*bnxt_doorbell_rx_cq)(void *, bool); +typedef void (*bnxt_doorbell_tx_cq)(void *, bool); +typedef void (*bnxt_doorbell_nq)(void *, bool); + +typedef struct bnxt_doorbell_ops { + bnxt_doorbell_tx bnxt_db_tx; + bnxt_doorbell_rx bnxt_db_rx; + bnxt_doorbell_rx_cq bnxt_db_rx_cq; + bnxt_doorbell_tx_cq bnxt_db_tx_cq; + bnxt_doorbell_nq bnxt_db_nq; +} bnxt_dooorbell_ops_t; +/* NVRAM access */ +enum bnxt_nvm_directory_type { + BNX_DIR_TYPE_UNUSED = 0, + BNX_DIR_TYPE_PKG_LOG = 1, + BNX_DIR_TYPE_UPDATE = 2, + BNX_DIR_TYPE_CHIMP_PATCH = 3, + BNX_DIR_TYPE_BOOTCODE = 4, + BNX_DIR_TYPE_VPD = 5, + BNX_DIR_TYPE_EXP_ROM_MBA = 6, + BNX_DIR_TYPE_AVS = 7, + BNX_DIR_TYPE_PCIE = 8, + BNX_DIR_TYPE_PORT_MACRO = 9, + BNX_DIR_TYPE_APE_FW = 10, + BNX_DIR_TYPE_APE_PATCH = 11, + BNX_DIR_TYPE_KONG_FW = 12, + BNX_DIR_TYPE_KONG_PATCH = 13, + BNX_DIR_TYPE_BONO_FW = 14, + BNX_DIR_TYPE_BONO_PATCH = 15, + BNX_DIR_TYPE_TANG_FW = 16, + BNX_DIR_TYPE_TANG_PATCH = 17, + BNX_DIR_TYPE_BOOTCODE_2 = 18, + BNX_DIR_TYPE_CCM = 19, + BNX_DIR_TYPE_PCI_CFG = 20, + BNX_DIR_TYPE_TSCF_UCODE = 21, + BNX_DIR_TYPE_ISCSI_BOOT = 22, + BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, + BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, + BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26, + BNX_DIR_TYPE_EXT_PHY = 27, + BNX_DIR_TYPE_SHARED_CFG = 40, + BNX_DIR_TYPE_PORT_CFG = 41, + BNX_DIR_TYPE_FUNC_CFG = 42, + BNX_DIR_TYPE_MGMT_CFG = 48, + BNX_DIR_TYPE_MGMT_DATA = 49, + BNX_DIR_TYPE_MGMT_WEB_DATA = 50, + BNX_DIR_TYPE_MGMT_WEB_META = 51, + BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, + BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 +}; + +enum bnxnvm_pkglog_field_index { + BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, + BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, + BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, + BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, + BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, + BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 +}; + +#define BNX_DIR_ORDINAL_FIRST 0 +#define BNX_DIR_EXT_NONE 0 + +struct bnxt_bar_info { + struct resource *res; + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t size; + int rid; +}; + +struct bnxt_flow_ctrl { + bool rx; + bool tx; + bool autoneg; +}; + +struct bnxt_link_info { + uint8_t media_type; + uint8_t transceiver; + uint8_t phy_addr; + uint8_t phy_link_status; + uint8_t wire_speed; + uint8_t loop_back; + uint8_t link_up; + uint8_t last_link_up; + uint8_t duplex; + uint8_t last_duplex; + uint8_t last_phy_type; + struct bnxt_flow_ctrl flow_ctrl; + struct bnxt_flow_ctrl last_flow_ctrl; + uint8_t duplex_setting; + uint8_t auto_mode; +#define PHY_VER_LEN 3 + uint8_t phy_ver[PHY_VER_LEN]; + uint8_t phy_type; +#define BNXT_PHY_STATE_ENABLED 0 +#define BNXT_PHY_STATE_DISABLED 1 + uint8_t phy_state; + + uint16_t link_speed; + uint16_t support_speeds; + uint16_t support_speeds2; + uint16_t support_pam4_speeds; + uint16_t auto_link_speeds; + uint16_t auto_link_speeds2; + uint16_t auto_pam4_link_speeds; + uint16_t force_link_speed; + uint16_t force_link_speeds2; + uint16_t force_pam4_link_speed; + + bool force_pam4_speed; + bool force_speed2_nrz; + bool force_pam4_56_speed2; + bool force_pam4_112_speed2; + + uint16_t advertising; + uint16_t advertising_pam4; + + uint32_t preemphasis; + uint16_t support_auto_speeds; + uint16_t support_force_speeds; + uint16_t support_pam4_auto_speeds; + uint16_t support_pam4_force_speeds; + uint16_t support_auto_speeds2; + uint16_t support_force_speeds2; +#define BNXT_SIG_MODE_NRZ HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_NRZ +#define BNXT_SIG_MODE_PAM4 HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4 +#define BNXT_SIG_MODE_PAM4_112 HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4_112 + uint8_t req_signal_mode; + + uint8_t active_fec_sig_mode; + uint8_t sig_mode; + + /* copy of requested setting */ + uint8_t autoneg; +#define BNXT_AUTONEG_SPEED 1 +#define BNXT_AUTONEG_FLOW_CTRL 2 + uint8_t req_duplex; + uint16_t req_link_speed; + uint8_t module_status; + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; +}; + +enum bnxt_phy_type { + BNXT_MEDIA_CR = 0, + BNXT_MEDIA_LR, + BNXT_MEDIA_SR, + BNXT_MEDIA_ER, + BNXT_MEDIA_KR, + BNXT_MEDIA_AC, + BNXT_MEDIA_BASECX, + BNXT_MEDIA_BASET, + BNXT_MEDIA_BASEKX, + BNXT_MEDIA_BASESGMII, + BNXT_MEDIA_END +}; + +enum bnxt_cp_type { + BNXT_DEFAULT, + BNXT_TX, + BNXT_RX, + BNXT_SHARED +}; + +struct bnxt_queue_info { + uint8_t queue_id; + uint8_t queue_profile; +}; + +struct bnxt_func_info { + uint32_t fw_fid; + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint16_t max_rsscos_ctxs; + uint16_t max_cp_rings; + uint16_t max_tx_rings; + uint16_t max_rx_rings; + uint16_t max_hw_ring_grps; + uint16_t max_irqs; + uint16_t max_l2_ctxs; + uint16_t max_vnics; + uint16_t max_stat_ctxs; +}; + +struct bnxt_pf_info { +#define BNXT_FIRST_PF_FID 1 +#define BNXT_FIRST_VF_FID 128 + uint8_t port_id; + uint32_t first_vf_id; + uint16_t active_vfs; + uint16_t max_vfs; + uint32_t max_encap_records; + uint32_t max_decap_records; + uint32_t max_tx_em_flows; + uint32_t max_tx_wm_flows; + uint32_t max_rx_em_flows; + uint32_t max_rx_wm_flows; + unsigned long *vf_event_bmap; + uint16_t hwrm_cmd_req_pages; + void *hwrm_cmd_req_addr[4]; + bus_addr_t hwrm_cmd_req_dma_addr[4]; +}; + +struct bnxt_vf_info { + uint16_t fw_fid; + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint16_t max_rsscos_ctxs; + uint16_t max_cp_rings; + uint16_t max_tx_rings; + uint16_t max_rx_rings; + uint16_t max_hw_ring_grps; + uint16_t max_l2_ctxs; + uint16_t max_irqs; + uint16_t max_vnics; + uint16_t max_stat_ctxs; + uint32_t vlan; +#define BNXT_VF_QOS 0x1 +#define BNXT_VF_SPOOFCHK 0x2 +#define BNXT_VF_LINK_FORCED 0x4 +#define BNXT_VF_LINK_UP 0x8 + uint32_t flags; + uint32_t func_flags; /* func cfg flags */ + uint32_t min_tx_rate; + uint32_t max_tx_rate; + void *hwrm_cmd_req_addr; + bus_addr_t hwrm_cmd_req_dma_addr; +}; + +#define BNXT_PF(softc) (!((softc)->flags & BNXT_FLAG_VF)) +#define BNXT_VF(softc) ((softc)->flags & BNXT_FLAG_VF) + +struct bnxt_vlan_tag { + SLIST_ENTRY(bnxt_vlan_tag) next; + uint64_t filter_id; + uint16_t tag; +}; + +struct bnxt_vnic_info { + uint16_t id; + uint16_t def_ring_grp; + uint16_t cos_rule; + uint16_t lb_rule; + uint16_t mru; + + uint32_t rx_mask; + struct iflib_dma_info mc_list; + int mc_list_count; +#define BNXT_MAX_MC_ADDRS 16 + + uint32_t flags; +#define BNXT_VNIC_FLAG_DEFAULT 0x01 +#define BNXT_VNIC_FLAG_BD_STALL 0x02 +#define BNXT_VNIC_FLAG_VLAN_STRIP 0x04 + + uint64_t filter_id; + + uint16_t rss_id; + uint32_t rss_hash_type; + uint8_t rss_hash_key[HW_HASH_KEY_SIZE]; + struct iflib_dma_info rss_hash_key_tbl; + struct iflib_dma_info rss_grp_tbl; + SLIST_HEAD(vlan_head, bnxt_vlan_tag) vlan_tags; + struct iflib_dma_info vlan_tag_list; +}; + +struct bnxt_grp_info { + uint16_t stats_ctx; + uint16_t grp_id; + uint16_t rx_ring_id; + uint16_t cp_ring_id; + uint16_t ag_ring_id; +}; + +#define EPOCH_ARR_SZ 4096 + +struct bnxt_ring { + uint64_t paddr; + vm_offset_t doorbell; + caddr_t vaddr; + struct bnxt_softc *softc; + 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; + union { + u64 db_key64; + u32 db_key32; + }; + uint32_t db_ring_mask; + uint32_t db_epoch_mask; + uint8_t db_epoch_shift; + + uint64_t epoch_arr[EPOCH_ARR_SZ]; + bool epoch_bit; + +}; + +struct bnxt_cp_ring { + struct bnxt_ring ring; + struct if_irq irq; + uint32_t cons; + uint32_t raw_cons; + bool v_bit; /* Value of valid bit */ + struct ctx_hw_stats *stats; + uint32_t stats_ctx_id; + uint32_t last_idx; /* Used by RX rings only + * set to the last read pidx + */ + uint64_t int_count; + uint8_t toggle; + uint8_t type; +#define Q_TYPE_TX 1 +#define Q_TYPE_RX 2 +}; + +struct bnxt_full_tpa_start { + struct rx_tpa_start_cmpl low; + struct rx_tpa_start_cmpl_hi high; +}; + +/* All the version information for the part */ +#define BNXT_VERSTR_SIZE (3*3+2+1) /* ie: "255.255.255\0" */ +#define BNXT_NAME_SIZE 17 +#define FW_VER_STR_LEN 32 +#define BC_HWRM_STR_LEN 21 +struct bnxt_ver_info { + uint8_t hwrm_if_major; + uint8_t hwrm_if_minor; + uint8_t hwrm_if_update; + char hwrm_if_ver[BNXT_VERSTR_SIZE]; + char driver_hwrm_if_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]; + + char hwrm_fw_name[BNXT_NAME_SIZE]; + char mgmt_fw_name[BNXT_NAME_SIZE]; + char netctrl_fw_name[BNXT_NAME_SIZE]; + char roce_fw_name[BNXT_NAME_SIZE]; + char phy_vendor[BNXT_NAME_SIZE]; + char phy_partnumber[BNXT_NAME_SIZE]; + + uint16_t chip_num; + uint8_t chip_rev; + uint8_t chip_metal; + uint8_t chip_bond_id; + uint8_t chip_type; + + uint8_t hwrm_min_major; + uint8_t hwrm_min_minor; + uint8_t hwrm_min_update; + uint64_t fw_ver_code; +#define BNXT_FW_VER_CODE(maj, min, bld, rsv) \ + ((uint64_t)(maj) << 48 | (uint64_t)(min) << 32 | (uint64_t)(bld) << 16 | (rsv)) +#define BNXT_FW_MAJ(softc) ((softc)->ver_info->fw_ver_code >> 48) +#define BNXT_FW_MIN(softc) (((softc)->ver_info->fw_ver_code >> 32) & 0xffff) +#define BNXT_FW_BLD(softc) (((softc)->ver_info->fw_ver_code >> 16) & 0xffff) +#define BNXT_FW_RSV(softc) (((softc)->ver_info->fw_ver_code) & 0xffff) + + struct sysctl_ctx_list ver_ctx; + struct sysctl_oid *ver_oid; +}; + +struct bnxt_nvram_info { + uint16_t mfg_id; + uint16_t device_id; + uint32_t sector_size; + uint32_t size; + uint32_t reserved_size; + uint32_t available_size; + + struct sysctl_ctx_list nvm_ctx; + struct sysctl_oid *nvm_oid; +}; + +struct bnxt_func_qcfg { + uint16_t alloc_completion_rings; + uint16_t alloc_tx_rings; + uint16_t alloc_rx_rings; + uint16_t alloc_vnics; +}; + +struct bnxt_hw_lro { + uint16_t enable; + uint16_t is_mode_gro; + uint16_t max_agg_segs; + uint16_t max_aggs; + 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; + 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 { + 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; +}; + +#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_INPUT_SRQ_PG_SIZE_PG_8K; \ + else if (BNXT_PAGE_SIZE == 0x10000) \ + attr = HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_PG_SIZE_PG_64K; \ + else \ + attr = HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_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 last:1; + u8 mem_valid:1; + 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_TIM + 1) +#define BNXT_CTX_L2_MAX (BNXT_CTX_FTQM + 1) + +#define BNXT_CTX_V2_MAX (HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE + 1) +#define BNXT_CTX_SRT_TRACE HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT_TRACE +#define BNXT_CTX_ROCE_HWRM_TRACE HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE +#define BNXT_CTX_INV ((u16)-1) + +struct bnxt_ctx_mem_info { + u8 tqm_fp_rings_count; + + u32 flags; + #define BNXT_CTX_FLAG_INITED 0x01 + struct bnxt_ctx_mem_type ctx_arr[BNXT_CTX_V2_MAX]; +}; + +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; +}; + +enum bnxt_type_ets { + BNXT_TYPE_ETS_TSA = 0, + BNXT_TYPE_ETS_PRI2TC, + BNXT_TYPE_ETS_TCBW, + BNXT_TYPE_ETS_MAX +}; + +static const char *const BNXT_ETS_TYPE_STR[] = { + "tsa", + "pri2tc", + "tcbw", +}; + +static const char *const BNXT_ETS_HELP_STR[] = { + "X is 1 (strict), 0 (ets)", + "TC values for pri 0 to 7", + "TC BW values for pri 0 to 7, Sum should be 100", +}; + +#define BNXT_HWRM_MAX_REQ_LEN (softc->hwrm_max_req_len) + +struct bnxt_softc_list { + SLIST_ENTRY(bnxt_softc_list) next; + struct bnxt_softc *softc; +}; + +#ifndef BIT_ULL +#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; +}; + +enum bnxt_health_severity { + SEVERITY_NORMAL = 0, + SEVERITY_WARNING, + SEVERITY_RECOVERABLE, + SEVERITY_FATAL, +}; + +enum bnxt_health_remedy { + REMEDY_DEVLINK_RECOVER, + REMEDY_POWER_CYCLE_DEVICE, + REMEDY_POWER_CYCLE_HOST, + REMEDY_FW_UPDATE, + REMEDY_HW_REPLACE, +}; + +struct bnxt_fw_health { + u32 flags; + u32 polling_dsecs; + u32 master_func_wait_dsecs; + u32 normal_func_wait_dsecs; + u32 post_reset_wait_dsecs; + u32 post_reset_max_wait_dsecs; + u32 regs[4]; + u32 mapped_regs[4]; +#define BNXT_FW_HEALTH_REG 0 +#define BNXT_FW_HEARTBEAT_REG 1 +#define BNXT_FW_RESET_CNT_REG 2 +#define BNXT_FW_RESET_INPROG_REG 3 + u32 fw_reset_inprog_reg_mask; + u32 last_fw_heartbeat; + u32 last_fw_reset_cnt; + u8 enabled:1; + u8 primary:1; + u8 status_reliable:1; + u8 resets_reliable:1; + u8 tmr_multiplier; + u8 tmr_counter; + u8 fw_reset_seq_cnt; + u32 fw_reset_seq_regs[16]; + u32 fw_reset_seq_vals[16]; + u32 fw_reset_seq_delay_msec[16]; + u32 echo_req_data1; + u32 echo_req_data2; + struct devlink_health_reporter *fw_reporter; + struct mutex lock; + enum bnxt_health_severity severity; + enum bnxt_health_remedy remedy; + u32 arrests; + u32 discoveries; + u32 survivals; + u32 fatalities; + u32 diagnoses; +}; + +#define BNXT_FW_HEALTH_REG_TYPE_MASK 3 +#define BNXT_FW_HEALTH_REG_TYPE_CFG 0 +#define BNXT_FW_HEALTH_REG_TYPE_GRC 1 +#define BNXT_FW_HEALTH_REG_TYPE_BAR0 2 +#define BNXT_FW_HEALTH_REG_TYPE_BAR1 3 + +#define BNXT_FW_HEALTH_REG_TYPE(reg) ((reg) & BNXT_FW_HEALTH_REG_TYPE_MASK) +#define BNXT_FW_HEALTH_REG_OFF(reg) ((reg) & ~BNXT_FW_HEALTH_REG_TYPE_MASK) + +#define BNXT_FW_HEALTH_WIN_BASE 0x3000 +#define BNXT_FW_HEALTH_WIN_MAP_OFF 8 + +#define BNXT_FW_HEALTH_WIN_OFF(reg) (BNXT_FW_HEALTH_WIN_BASE + \ + ((reg) & BNXT_GRC_OFFSET_MASK)) + +#define BNXT_FW_STATUS_HEALTH_MSK 0xffff +#define BNXT_FW_STATUS_HEALTHY 0x8000 +#define BNXT_FW_STATUS_SHUTDOWN 0x100000 +#define BNXT_FW_STATUS_RECOVERING 0x400000 + +#define BNXT_FW_IS_HEALTHY(sts) (((sts) & BNXT_FW_STATUS_HEALTH_MSK) ==\ + BNXT_FW_STATUS_HEALTHY) + +#define BNXT_FW_IS_BOOTING(sts) (((sts) & BNXT_FW_STATUS_HEALTH_MSK) < \ + BNXT_FW_STATUS_HEALTHY) + +#define BNXT_FW_IS_ERR(sts) (((sts) & BNXT_FW_STATUS_HEALTH_MSK) > \ + BNXT_FW_STATUS_HEALTHY) + +#define BNXT_FW_IS_RECOVERING(sts) (BNXT_FW_IS_ERR(sts) && \ + ((sts) & BNXT_FW_STATUS_RECOVERING)) + +#define BNXT_FW_RETRY 5 +#define BNXT_FW_IF_RETRY 10 +#define BNXT_FW_SLOT_RESET_RETRY 4 + +#define BNXT_GRCPF_REG_CHIMP_COMM 0x0 +#define BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER 0x100 +#define BNXT_GRCPF_REG_WINDOW_BASE_OUT 0x400 +#define BNXT_GRCPF_REG_SYNC_TIME 0x480 +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ 0x488 +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_PER_MSK 0xffffffUL +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_PER_SFT 0 +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_VAL_MSK 0x1f000000UL +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_VAL_SFT 24 +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_SIGN_MSK 0x20000000UL +#define BNXT_GRCPF_REG_SYNC_TIME_ADJ_SIGN_SFT 29 + +#define BNXT_GRC_REG_STATUS_P5 0x520 + +#define BNXT_GRCPF_REG_KONG_COMM 0xA00 +#define BNXT_GRCPF_REG_KONG_COMM_TRIGGER 0xB00 + +#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014 +#define BNXT_CAG_REG_BASE 0x300000 + +#define BNXT_GRC_REG_CHIP_NUM 0x48 +#define BNXT_GRC_REG_BASE 0x260000 + +#define BNXT_TS_REG_TIMESYNC_TS0_LOWER 0x640180c +#define BNXT_TS_REG_TIMESYNC_TS0_UPPER 0x6401810 + +#define BNXT_GRC_BASE_MASK 0xfffff000 +#define BNXT_GRC_OFFSET_MASK 0x00000ffc + +#define NQE_CN_TYPE(type) ((type) & NQ_CN_TYPE_MASK) +#define NQE_CN_TOGGLE(type) (((type) & NQ_CN_TOGGLE_MASK) >> \ + NQ_CN_TOGGLE_SFT) + +#define DB_EPOCH(ring, idx) (((idx) & (ring)->db_epoch_mask) << \ + ((ring)->db_epoch_shift)) + +#define DB_TOGGLE(tgl) ((tgl) << DBR_TOGGLE_SFT) + +#define DB_RING_IDX_CMP(ring, idx) (((idx) & (ring)->db_ring_mask) | \ + DB_EPOCH(ring, idx)) + +#define DB_RING_IDX(ring, idx, bit) (((idx) & (ring)->db_ring_mask) | \ + ((bit) << (24))) + +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; + uint32_t function; + uint32_t dev_fn; + struct ifmedia *media; + struct bnxt_ctx_mem_info *ctx_mem; + struct bnxt_hw_resc hw_resc; + struct bnxt_softc_list list; + + struct bnxt_bar_info hwrm_bar; + struct bnxt_bar_info doorbell_bar; + struct bnxt_link_info link_info; +#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_FW_CAP_NEW_RM 0x0010 +#define BNXT_FLAG_CHIP_P5 0x0020 +#define BNXT_FLAG_TPA 0x0040 +#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) +#define BNXT_FLAG_CHIP_P7 0x1000 + 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_irqs; + struct bnxt_msix_tbl *irq_tbl; + + struct bnxt_func_info func; + struct bnxt_func_qcfg fn_qcfg; + struct bnxt_pf_info pf; + struct bnxt_vf_info vf; + + uint16_t hwrm_cmd_seq; + uint32_t hwrm_cmd_timeo; /* milliseconds */ + struct iflib_dma_info hwrm_cmd_resp; + struct iflib_dma_info hwrm_short_cmd_req_addr; + /* Interrupt info for HWRM */ + 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 + uint8_t max_tc; + uint8_t max_lltc; + struct bnxt_queue_info tx_q_info[BNXT_MAX_QUEUE]; + struct bnxt_queue_info rx_q_info[BNXT_MAX_QUEUE]; + uint8_t tc_to_qidx[BNXT_MAX_QUEUE]; + uint8_t tx_q_ids[BNXT_MAX_QUEUE]; + uint8_t rx_q_ids[BNXT_MAX_QUEUE]; + uint8_t tx_max_q; + uint8_t rx_max_q; + uint8_t is_asym_q; + + struct bnxt_ieee_ets *ieee_ets; + struct bnxt_ieee_pfc *ieee_pfc; + uint8_t dcbx_cap; + uint8_t default_pri; + uint8_t max_dscp_value; + + uint64_t admin_ticks; + struct iflib_dma_info hw_rx_port_stats; + struct iflib_dma_info hw_tx_port_stats; + struct rx_port_stats *rx_port_stats; + struct tx_port_stats *tx_port_stats; + + struct iflib_dma_info hw_tx_port_stats_ext; + struct iflib_dma_info hw_rx_port_stats_ext; + struct tx_port_stats_ext *tx_port_stats_ext; + struct rx_port_stats_ext *rx_port_stats_ext; + + uint16_t fw_rx_stats_ext_size; + uint16_t fw_tx_stats_ext_size; + uint16_t hw_ring_stats_size; + + uint8_t tx_pri2cos_idx[8]; + uint8_t rx_pri2cos_idx[8]; + bool pri2cos_valid; + + uint64_t tx_bytes_pri[8]; + uint64_t tx_packets_pri[8]; + uint64_t rx_bytes_pri[8]; + uint64_t rx_packets_pri[8]; + + uint8_t port_count; + 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[BNXT_MAX_NUM_QUEUES]; + int ntxqsets; + + struct bnxt_vnic_info vnic_info; + struct bnxt_ring *ag_rings; + struct bnxt_ring *rx_rings; + struct bnxt_cp_ring *rx_cp_rings; + struct bnxt_grp_info *grp_info; + struct iflib_dma_info rx_stats[BNXT_MAX_NUM_QUEUES]; + int nrxqsets; + uint16_t rx_buf_size; + + 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 task def_cp_task; + int db_size; + int legacy_db_size; + struct bnxt_doorbell_ops db_ops; + + struct sysctl_ctx_list hw_stats; + struct sysctl_oid *hw_stats_oid; + struct sysctl_ctx_list hw_lro_ctx; + struct sysctl_oid *hw_lro_oid; + struct sysctl_ctx_list flow_ctrl_ctx; + struct sysctl_oid *flow_ctrl_oid; + struct sysctl_ctx_list dcb_ctx; + struct sysctl_oid *dcb_oid; + + struct bnxt_ver_info *ver_info; + struct bnxt_nvram_info *nvm_info; + bool wol; + bool is_dev_init; + struct bnxt_hw_lro hw_lro; + uint8_t wol_filter_id; + uint16_t rx_coal_usecs; + uint16_t rx_coal_usecs_irq; + uint16_t rx_coal_frames; + uint16_t rx_coal_frames_irq; + uint16_t tx_coal_usecs; + uint16_t tx_coal_usecs_irq; + uint16_t tx_coal_frames; + uint16_t tx_coal_frames_irq; + +#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2) +#define BNXT_DEF_STATS_COAL_TICKS 1000000 +#define BNXT_MIN_STATS_COAL_TICKS 250000 +#define BNXT_MAX_STATS_COAL_TICKS 1000000 + + uint64_t fw_cap; + #define BNXT_FW_CAP_SHORT_CMD BIT_ULL(0) + #define BNXT_FW_CAP_LLDP_AGENT BIT_ULL(1) + #define BNXT_FW_CAP_DCBX_AGENT BIT_ULL(2) + #define BNXT_FW_CAP_NEW_RM BIT_ULL(3) + #define BNXT_FW_CAP_IF_CHANGE BIT_ULL(4) + #define BNXT_FW_CAP_LINK_ADMIN BIT_ULL(5) + #define BNXT_FW_CAP_VF_RES_MIN_GUARANTEED BIT_ULL(6) + #define BNXT_FW_CAP_KONG_MB_CHNL BIT_ULL(7) + #define BNXT_FW_CAP_ADMIN_MTU BIT_ULL(8) + #define BNXT_FW_CAP_ADMIN_PF BIT_ULL(9) + #define BNXT_FW_CAP_OVS_64BIT_HANDLE BIT_ULL(10) + #define BNXT_FW_CAP_TRUSTED_VF BIT_ULL(11) + #define BNXT_FW_CAP_VF_VNIC_NOTIFY BIT_ULL(12) + #define BNXT_FW_CAP_ERROR_RECOVERY BIT_ULL(13) + #define BNXT_FW_CAP_PKG_VER BIT_ULL(14) + #define BNXT_FW_CAP_CFA_ADV_FLOW BIT_ULL(15) + #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2 BIT_ULL(16) + #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED BIT_ULL(17) + #define BNXT_FW_CAP_EXT_STATS_SUPPORTED BIT_ULL(18) + #define BNXT_FW_CAP_SECURE_MODE BIT_ULL(19) + #define BNXT_FW_CAP_ERR_RECOVER_RELOAD BIT_ULL(20) + #define BNXT_FW_CAP_HOT_RESET BIT_ULL(21) + #define BNXT_FW_CAP_CRASHDUMP BIT_ULL(23) + #define BNXT_FW_CAP_VLAN_RX_STRIP BIT_ULL(24) + #define BNXT_FW_CAP_VLAN_TX_INSERT BIT_ULL(25) + #define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED BIT_ULL(26) + #define BNXT_FW_CAP_CFA_EEM BIT_ULL(27) + #define BNXT_FW_CAP_DBG_QCAPS BIT_ULL(29) + #define BNXT_FW_CAP_RING_MONITOR BIT_ULL(30) + #define BNXT_FW_CAP_ECN_STATS BIT_ULL(31) + #define BNXT_FW_CAP_TRUFLOW BIT_ULL(32) + #define BNXT_FW_CAP_VF_CFG_FOR_PF BIT_ULL(33) + #define BNXT_FW_CAP_PTP_PPS BIT_ULL(34) + #define BNXT_FW_CAP_HOT_RESET_IF BIT_ULL(35) + #define BNXT_FW_CAP_LIVEPATCH BIT_ULL(36) + #define BNXT_FW_CAP_NPAR_1_2 BIT_ULL(37) + #define BNXT_FW_CAP_RSS_HASH_TYPE_DELTA BIT_ULL(38) + #define BNXT_FW_CAP_PTP_RTC BIT_ULL(39) + #define BNXT_FW_CAP_TRUFLOW_EN BIT_ULL(40) + #define BNXT_TRUFLOW_EN(bp) ((bp)->fw_cap & BNXT_FW_CAP_TRUFLOW_EN) + #define BNXT_FW_CAP_RX_ALL_PKT_TS BIT_ULL(41) + #define BNXT_FW_CAP_BACKING_STORE_V2 BIT_ULL(42) + #define BNXT_FW_CAP_DBR_SUPPORTED BIT_ULL(43) + #define BNXT_FW_CAP_GENERIC_STATS BIT_ULL(44) + #define BNXT_FW_CAP_DBR_PACING_SUPPORTED BIT_ULL(45) + #define BNXT_FW_CAP_PTP_PTM BIT_ULL(46) + #define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(47) + #define BNXT_FW_CAP_ENABLE_RDMA_SRIOV BIT_ULL(48) + #define BNXT_FW_CAP_RSS_TCAM BIT_ULL(49) + uint32_t lpi_tmr_lo; + uint32_t lpi_tmr_hi; + /* copied from flags and flags2 in hwrm_port_phy_qcaps_output */ + uint16_t phy_flags; +#define BNXT_PHY_FL_EEE_CAP HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EEE_SUPPORTED +#define BNXT_PHY_FL_EXT_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EXTERNAL_LPBK_SUPPORTED +#define BNXT_PHY_FL_AN_PHY_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_AUTONEG_LPBK_SUPPORTED +#define BNXT_PHY_FL_SHARED_PORT_CFG HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_SHARED_PHY_CFG_SUPPORTED +#define BNXT_PHY_FL_PORT_STATS_NO_RESET HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_CUMULATIVE_COUNTERS_ON_RESET +#define BNXT_PHY_FL_NO_PHY_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_LOCAL_LPBK_NOT_SUPPORTED +#define BNXT_PHY_FL_FW_MANAGED_LKDN HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_FW_MANAGED_LINK_DOWN +#define BNXT_PHY_FL_NO_FCS HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_NO_FCS +#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; + + struct work_struct sp_task; + unsigned long sp_event; +#define BNXT_RX_MASK_SP_EVENT 0 +#define BNXT_RX_NTP_FLTR_SP_EVENT 1 +#define BNXT_LINK_CHNG_SP_EVENT 2 +#define BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT 3 +#define BNXT_VXLAN_ADD_PORT_SP_EVENT 4 +#define BNXT_VXLAN_DEL_PORT_SP_EVENT 5 +#define BNXT_RESET_TASK_SP_EVENT 6 +#define BNXT_RST_RING_SP_EVENT 7 +#define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8 +#define BNXT_PERIODIC_STATS_SP_EVENT 9 +#define BNXT_HWRM_PORT_MODULE_SP_EVENT 10 +#define BNXT_RESET_TASK_SILENT_SP_EVENT 11 +#define BNXT_GENEVE_ADD_PORT_SP_EVENT 12 +#define BNXT_GENEVE_DEL_PORT_SP_EVENT 13 +#define BNXT_LINK_SPEED_CHNG_SP_EVENT 14 +#define BNXT_FLOW_STATS_SP_EVENT 15 +#define BNXT_UPDATE_PHY_SP_EVENT 16 +#define BNXT_RING_COAL_NOW_SP_EVENT 17 +#define BNXT_FW_RESET_NOTIFY_SP_EVENT 18 +#define BNXT_FW_EXCEPTION_SP_EVENT 19 +#define BNXT_VF_VNIC_CHANGE_SP_EVENT 20 +#define BNXT_LINK_CFG_CHANGE_SP_EVENT 21 +#define BNXT_PTP_CURRENT_TIME_EVENT 22 +#define BNXT_FW_ECHO_REQUEST_SP_EVENT 23 +#define BNXT_VF_CFG_CHNG_SP_EVENT 24 + + struct delayed_work fw_reset_task; + int fw_reset_state; +#define BNXT_FW_RESET_STATE_POLL_VF 1 +#define BNXT_FW_RESET_STATE_RESET_FW 2 +#define BNXT_FW_RESET_STATE_ENABLE_DEV 3 +#define BNXT_FW_RESET_STATE_POLL_FW 4 +#define BNXT_FW_RESET_STATE_OPENING 5 +#define BNXT_FW_RESET_STATE_POLL_FW_DOWN 6 + u16 fw_reset_min_dsecs; +#define BNXT_DFLT_FW_RST_MIN_DSECS 20 + u16 fw_reset_max_dsecs; +#define BNXT_DFLT_FW_RST_MAX_DSECS 60 + unsigned long fw_reset_timestamp; + + struct bnxt_fw_health *fw_health; +}; + +struct bnxt_filter_info { + STAILQ_ENTRY(bnxt_filter_info) next; + uint64_t fw_l2_filter_id; +#define INVALID_MAC_INDEX ((uint16_t)-1) + uint16_t mac_index; + + /* Filter Characteristics */ + uint32_t flags; + uint32_t enables; + uint8_t l2_addr[ETHER_ADDR_LEN]; + uint8_t l2_addr_mask[ETHER_ADDR_LEN]; + uint16_t l2_ovlan; + uint16_t l2_ovlan_mask; + uint16_t l2_ivlan; + uint16_t l2_ivlan_mask; + uint8_t t_l2_addr[ETHER_ADDR_LEN]; + uint8_t t_l2_addr_mask[ETHER_ADDR_LEN]; + uint16_t t_l2_ovlan; + uint16_t t_l2_ovlan_mask; + uint16_t t_l2_ivlan; + uint16_t t_l2_ivlan_mask; + uint8_t tunnel_type; + uint16_t mirror_vnic_id; + uint32_t vni; + uint8_t pri_hint; + uint64_t l2_filter_id_hint; +}; + +#define I2C_DEV_ADDR_A0 0xa0 +#define BNXT_MAX_PHY_I2C_RESP_SIZE 64 + +/* Function declarations */ +void bnxt_report_link(struct bnxt_softc *softc); +bool bnxt_check_hwrm_version(struct bnxt_softc *softc); +struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, char *name); +int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *bp, uint16_t i2c_addr, + uint16_t page_number, uint8_t bank, bool bank_sel_en, uint16_t start_addr, + uint16_t data_length, uint8_t *buf); +void bnxt_dcb_init(struct bnxt_softc *softc); +void bnxt_dcb_free(struct bnxt_softc *softc); +uint8_t bnxt_dcb_setdcbx(struct bnxt_softc *softc, uint8_t mode); +uint8_t bnxt_dcb_getdcbx(struct bnxt_softc *softc); +int bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets); +int bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets); +uint8_t get_phy_type(struct bnxt_softc *softc); +int bnxt_dcb_ieee_getpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc); +int bnxt_dcb_ieee_setpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc); +int bnxt_dcb_ieee_setapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app); +int bnxt_dcb_ieee_delapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app); +int bnxt_dcb_ieee_listapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + size_t nitems, int *num_inputs); + +#endif /* _BNXT_H */ 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..c4c9e789cf3e --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.h @@ -0,0 +1,76 @@ +/*- + * 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; +}; +#define MODULE_DEVICE_TABLE_BUS_auxiliary(_bus, _table) + +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_dcb.c b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c new file mode 100644 index 000000000000..e0643f200021 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c @@ -0,0 +1,864 @@ +/*- + * 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 <sys/endian.h> +#include <linux/errno.h> +#include <linux/bitops.h> + +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include "bnxt_dcb.h" +#include "hsi_struct_def.h" + +static int +bnxt_tx_queue_to_tc(struct bnxt_softc *softc, uint8_t queue_id) +{ + int i, j; + + for (i = 0; i < softc->max_tc; i++) { + if (softc->tx_q_info[i].queue_id == queue_id) { + for (j = 0; j < softc->max_tc; j++) { + if (softc->tc_to_qidx[j] == i) + return j; + } + } + } + return -EINVAL; +} + +static int +bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc *softc, + struct bnxt_ieee_ets *ets, + uint32_t path_dir) +{ + struct hwrm_queue_pri2cos_cfg_input req = {0}; + struct bnxt_queue_info *q_info; + uint8_t *pri2cos; + int i; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_CFG); + + req.flags = htole32(path_dir | HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN); + if (path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR || + path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX) + q_info = softc->tx_q_info; + else + q_info = softc->rx_q_info; + pri2cos = &req.pri0_cos_queue_id; + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { + uint8_t qidx; + + req.enables |= htole32(HWRM_QUEUE_PRI2COS_CFG_INPUT_ENABLES_PRI0_COS_QUEUE_ID << i); + + qidx = softc->tc_to_qidx[ets->prio_tc[i]]; + pri2cos[i] = q_info[qidx].queue_id; + } + return _hwrm_send_message(softc, &req, sizeof(req)); +} + +static int +bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) +{ + struct hwrm_queue_pri2cos_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_queue_pri2cos_qcfg_input req = {0}; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG); + + req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (!rc) { + uint8_t *pri2cos = &resp->pri0_cos_queue_id; + int i; + + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { + uint8_t queue_id = pri2cos[i]; + int tc; + + tc = bnxt_tx_queue_to_tc(softc, queue_id); + if (tc >= 0) + ets->prio_tc[i] = tc; + } + } + return rc; +} + +static int +bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, + uint8_t max_tc) +{ + struct hwrm_queue_cos2bw_cfg_input req = {0}; + struct bnxt_cos2bw_cfg cos2bw; + void *data; + int i; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_CFG); + + for (i = 0; i < max_tc; i++) { + uint8_t qidx = softc->tc_to_qidx[i]; + + req.enables |= + htole32(HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID << qidx); + + memset(&cos2bw, 0, sizeof(cos2bw)); + cos2bw.queue_id = softc->tx_q_info[qidx].queue_id; + if (ets->tc_tsa[i] == BNXT_IEEE_8021QAZ_TSA_STRICT) { + cos2bw.tsa = + HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP; + cos2bw.pri_lvl = i; + } else { + cos2bw.tsa = + HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS; + cos2bw.bw_weight = ets->tc_tx_bw[i]; + /* older firmware requires min_bw to be set to the + * same weight value in percent. + */ + if (BNXT_FW_MAJ(softc) < 218) { + cos2bw.min_bw = + htole32((ets->tc_tx_bw[i] * 100) | + BW_VALUE_UNIT_PERCENT1_100); + } + } + data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4); + memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4); + if (qidx == 0) { + req.queue_id0 = cos2bw.queue_id; + req.unused_0 = 0; + } + } + return _hwrm_send_message(softc, &req, sizeof(req)); +} + +static int +bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) +{ + struct hwrm_queue_cos2bw_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_queue_cos2bw_qcfg_input req = {0}; + struct bnxt_cos2bw_cfg cos2bw; + uint8_t *data; + int rc, i; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_QCFG); + + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) { + return rc; + } + + data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); + for (i = 0; i < softc->max_tc; i++, data += sizeof(cos2bw.cfg)) { + int tc; + + memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg)); + if (i == 0) + cos2bw.queue_id = resp->queue_id0; + + tc = bnxt_tx_queue_to_tc(softc, cos2bw.queue_id); + if (tc < 0) + continue; + + if (cos2bw.tsa == HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP) { + ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_STRICT; + } else { + ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_ETS; + ets->tc_tx_bw[tc] = cos2bw.bw_weight; + } + } + return 0; +} + +static int +bnxt_queue_remap(struct bnxt_softc *softc, unsigned int lltc_mask) +{ + unsigned long qmap = 0; + int max = softc->max_tc; + int i, j, rc; + + /* Assign lossless TCs first */ + for (i = 0, j = 0; i < max; ) { + if (lltc_mask & (1 << i)) { + if (BNXT_LLQ(softc->rx_q_info[j].queue_profile)) { + softc->tc_to_qidx[i] = j; + __set_bit(j, &qmap); + i++; + } + j++; + continue; + } + i++; + } + + for (i = 0, j = 0; i < max; i++) { + if (lltc_mask & (1 << i)) + continue; + j = find_next_zero_bit(&qmap, max, j); + softc->tc_to_qidx[i] = j; + __set_bit(j, &qmap); + j++; + } + + if (softc->ieee_ets) { + rc = bnxt_hwrm_queue_cos2bw_cfg(softc, softc->ieee_ets, softc->max_tc); + if (rc) { + device_printf(softc->dev, "failed to config BW, rc = %d\n", rc); + return rc; + } + rc = bnxt_hwrm_queue_pri2cos_cfg(softc, softc->ieee_ets, + HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR); + if (rc) { + device_printf(softc->dev, "failed to config prio, rc = %d\n", rc); + return rc; + } + } + return 0; +} + +static int +bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) +{ + struct hwrm_queue_pfcenable_cfg_input req = {0}; + struct bnxt_ieee_ets *my_ets = softc->ieee_ets; + unsigned int tc_mask = 0, pri_mask = 0; + uint8_t i, pri, lltc_count = 0; + bool need_q_remap = false; + + if (!my_ets) + return -EINVAL; + + for (i = 0; i < softc->max_tc; i++) { + for (pri = 0; pri < BNXT_IEEE_8021QAZ_MAX_TCS; pri++) { + if ((pfc->pfc_en & (1 << pri)) && + (my_ets->prio_tc[pri] == i)) { + pri_mask |= 1 << pri; + tc_mask |= 1 << i; + } + } + if (tc_mask & (1 << i)) + lltc_count++; + } + + if (lltc_count > softc->max_lltc) { + device_printf(softc->dev, + "Hardware doesn't support %d lossless queues " + "to configure PFC (cap %d)\n", lltc_count, softc->max_lltc); + return -EINVAL; + } + + for (i = 0; i < softc->max_tc; i++) { + if (tc_mask & (1 << i)) { + uint8_t qidx = softc->tc_to_qidx[i]; + + if (!BNXT_LLQ(softc->rx_q_info[qidx].queue_profile)) { + need_q_remap = true; + break; + } + } + } + + if (need_q_remap) + bnxt_queue_remap(softc, tc_mask); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_CFG); + + req.flags = htole32(pri_mask); + return _hwrm_send_message(softc, &req, sizeof(req)); +} + +static int +bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) +{ + struct hwrm_queue_pfcenable_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_queue_pfcenable_qcfg_input req = {0}; + uint8_t pri_mask; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_QCFG); + + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) { + return rc; + } + + pri_mask = le32toh(resp->flags); + pfc->pfc_en = pri_mask; + return 0; +} + +static int +bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + size_t nitems, int *num_inputs) +{ + struct hwrm_fw_get_structured_data_input get = {0}; + struct hwrm_struct_data_dcbx_app *fw_app; + struct hwrm_struct_hdr *data; + struct iflib_dma_info dma_data; + size_t data_len; + int rc, n, i; + + if (softc->hwrm_spec_code < 0x10601) + return 0; + + bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); + + n = BNXT_IEEE_8021QAZ_MAX_TCS; + data_len = sizeof(*data) + sizeof(*fw_app) * n; + rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + get.dest_data_addr = htole64(dma_data.idi_paddr); + get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); + get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); + get.count = 0; + rc = _hwrm_send_message(softc, &get, sizeof(get)); + if (rc) + goto set_app_exit; + + data = (void *)dma_data.idi_vaddr; + fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); + + if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { + rc = -ENODEV; + goto set_app_exit; + } + + n = data->count; + for (i = 0; i < n && *num_inputs < nitems; i++, fw_app++) { + app[*num_inputs].priority = fw_app->priority; + app[*num_inputs].protocol = htobe16(fw_app->protocol_id); + app[*num_inputs].selector = fw_app->protocol_selector; + (*num_inputs)++; + } + +set_app_exit: + iflib_dma_free(&dma_data); + return rc; +} + +static int +bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + bool add) +{ + struct hwrm_fw_set_structured_data_input set = {0}; + struct hwrm_fw_get_structured_data_input get = {0}; + struct hwrm_struct_data_dcbx_app *fw_app; + struct hwrm_struct_hdr *data; + struct iflib_dma_info dma_data; + size_t data_len; + int rc, n, i; + + if (softc->hwrm_spec_code < 0x10601) + return 0; + + bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); + + n = BNXT_IEEE_8021QAZ_MAX_TCS; + data_len = sizeof(*data) + sizeof(*fw_app) * n; + rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + get.dest_data_addr = htole64(dma_data.idi_paddr); + get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); + get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); + get.count = 0; + rc = _hwrm_send_message(softc, &get, sizeof(get)); + if (rc) + goto set_app_exit; + + data = (void *)dma_data.idi_vaddr; + fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); + + if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { + rc = -ENODEV; + goto set_app_exit; + } + + n = data->count; + for (i = 0; i < n; i++, fw_app++) { + if (fw_app->protocol_id == htobe16(app->protocol) && + fw_app->protocol_selector == app->selector && + fw_app->priority == app->priority) { + if (add) + goto set_app_exit; + else + break; + } + } + if (add) { + /* append */ + n++; + fw_app->protocol_id = htobe16(app->protocol); + fw_app->protocol_selector = app->selector; + fw_app->priority = app->priority; + fw_app->valid = 1; + } else { + size_t len = 0; + + /* not found, nothing to delete */ + if (n == i) + goto set_app_exit; + + len = (n - 1 - i) * sizeof(*fw_app); + if (len) + memmove(fw_app, fw_app + 1, len); + n--; + memset(fw_app + n, 0, sizeof(*fw_app)); + } + data->count = n; + data->len = htole16(sizeof(*fw_app) * n); + data->subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); + + bnxt_hwrm_cmd_hdr_init(softc, &set, HWRM_FW_SET_STRUCTURED_DATA); + + set.src_data_addr = htole64(dma_data.idi_paddr); + set.data_len = htole16(sizeof(*data) + sizeof(*fw_app) * n); + set.hdr_cnt = 1; + rc = _hwrm_send_message(softc, &set, sizeof(set)); + +set_app_exit: + iflib_dma_free(&dma_data); + return rc; +} + +static int +bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc *softc) +{ + struct hwrm_queue_dscp_qcaps_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_queue_dscp_qcaps_input req = {0}; + int rc; + + softc->max_dscp_value = 0; + if (softc->hwrm_spec_code < 0x10800 || BNXT_VF(softc)) + return 0; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP_QCAPS); + + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (!rc) { + softc->max_dscp_value = (1 << resp->num_dscp_bits) - 1; + if (softc->max_dscp_value < 0x3f) + softc->max_dscp_value = 0; + } + return rc; +} + +static int +bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + size_t nitems, int *num_inputs) +{ + struct hwrm_queue_dscp2pri_qcfg_input req = {0}; + struct hwrm_queue_dscp2pri_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct bnxt_dscp2pri_entry *dscp2pri; + struct iflib_dma_info dma_data; + int rc, entry_cnt; + int i; + + if (softc->hwrm_spec_code < 0x10800) + return 0; + + rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri) * 128, &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + + dscp2pri = (void *)dma_data.idi_vaddr; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_QCFG); + + req.dest_data_addr = htole64(dma_data.idi_paddr); + req.dest_data_buffer_size = htole16(sizeof(*dscp2pri) * 64); + req.port_id = htole16(softc->pf.port_id); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + + if (rc) + goto end; + + entry_cnt = le16toh(resp->entry_cnt); + for (i = 0; i < entry_cnt && *num_inputs < nitems; i++) { + app[*num_inputs].priority = dscp2pri[i].pri; + app[*num_inputs].protocol = dscp2pri[i].dscp; + app[*num_inputs].selector = BNXT_IEEE_8021QAZ_APP_SEL_DSCP; + (*num_inputs)++; + } + +end: + iflib_dma_free(&dma_data); + return rc; +} + +static int +bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + bool add) +{ + struct hwrm_queue_dscp2pri_cfg_input req = {0}; + struct bnxt_dscp2pri_entry *dscp2pri; + struct iflib_dma_info dma_data; + int rc; + + if (softc->hwrm_spec_code < 0x10800) + return 0; + + rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri), &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_CFG); + + req.src_data_addr = htole64(dma_data.idi_paddr); + dscp2pri = (void *)dma_data.idi_vaddr; + dscp2pri->dscp = app->protocol; + if (add) + dscp2pri->mask = 0x3f; + else + dscp2pri->mask = 0; + dscp2pri->pri = app->priority; + req.entry_cnt = htole16(1); + req.port_id = htole16(softc->pf.port_id); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + + iflib_dma_free(&dma_data); + return rc; +} + +static int +bnxt_ets_validate(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, uint8_t *tc) +{ + int total_ets_bw = 0; + bool zero = false; + uint8_t max_tc = 0; + int i; + + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->prio_tc[i] > softc->max_tc) { + device_printf(softc->dev, "priority to TC mapping exceeds TC count %d\n", + ets->prio_tc[i]); + return -EINVAL; + } + if (ets->prio_tc[i] > max_tc) + max_tc = ets->prio_tc[i]; + + if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > softc->max_tc) + return -EINVAL; + + switch (ets->tc_tsa[i]) { + case BNXT_IEEE_8021QAZ_TSA_STRICT: + break; + case BNXT_IEEE_8021QAZ_TSA_ETS: + total_ets_bw += ets->tc_tx_bw[i]; + zero = zero || !ets->tc_tx_bw[i]; + break; + default: + return -ENOTSUPP; + } + } + if (total_ets_bw > 100) { + device_printf(softc->dev, "rejecting ETS config exceeding available bandwidth\n"); + return -EINVAL; + } + if (zero && total_ets_bw == 100) { + device_printf(softc->dev, "rejecting ETS config starving a TC\n"); + return -EINVAL; + } + + if (max_tc >= softc->max_tc) + *tc = softc->max_tc; + else + *tc = max_tc + 1; + return 0; +} + +int +bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) +{ + struct bnxt_ieee_ets *my_ets = softc->ieee_ets; + int rc; + + if (!my_ets) + return 0; + + rc = bnxt_hwrm_queue_cos2bw_qcfg(softc, my_ets); + if (rc) + goto error; + rc = bnxt_hwrm_queue_pri2cos_qcfg(softc, my_ets); + if (rc) + goto error; + + if (ets) { + ets->cbs = my_ets->cbs; + ets->ets_cap = softc->max_tc; + memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); + memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); + memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); + memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); + } + return 0; +error: + return rc; +} + +int +bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) +{ + uint8_t max_tc = 0; + int rc; + + if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || + !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) + return -EINVAL; + + rc = bnxt_ets_validate(softc, ets, &max_tc); + if (rc) + return rc; + + rc = bnxt_hwrm_queue_cos2bw_cfg(softc, ets, max_tc); + if (rc) + goto error; + + if (!softc->is_asym_q) { + rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, + HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR); + if (rc) + goto error; + } else { + rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, + HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX); + if (rc) + goto error; + + rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, + HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX); + if (rc) + goto error; + } + + memcpy(softc->ieee_ets, ets, sizeof(*ets)); + return 0; +error: + return rc; +} + +int +bnxt_dcb_ieee_getpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) +{ + struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc; + int rc; + + if (!my_pfc) + return -1; + + pfc->pfc_cap = softc->max_lltc; + + rc = bnxt_hwrm_queue_pfc_qcfg(softc, my_pfc); + if (rc) + return 0; + + pfc->pfc_en = my_pfc->pfc_en; + pfc->mbc = my_pfc->mbc; + pfc->delay = my_pfc->delay; + + return 0; +} + +int +bnxt_dcb_ieee_setpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) +{ + struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc; + int rc; + + if (!my_pfc) + return -1; + + if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || + !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST) || + (softc->phy_flags & BNXT_PHY_FL_NO_PAUSE)) + return -EINVAL; + + rc = bnxt_hwrm_queue_pfc_cfg(softc, pfc); + if (!rc) + memcpy(my_pfc, pfc, sizeof(*my_pfc)); + + return rc; +} + +static int +bnxt_dcb_ieee_dscp_app_prep(struct bnxt_softc *softc, struct bnxt_dcb_app *app) +{ + if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) { + if (!softc->max_dscp_value) + return -ENOTSUPP; + if (app->protocol > softc->max_dscp_value) + return -EINVAL; + } + return 0; +} + +int +bnxt_dcb_ieee_setapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app) +{ + int rc; + + + if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || + !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) + return -EINVAL; + + rc = bnxt_dcb_ieee_dscp_app_prep(softc, app); + if (rc) + return rc; + + if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE && + app->protocol == ETH_P_ROCE) || + (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM && + app->protocol == ROCE_V2_UDP_DPORT)) + rc = bnxt_hwrm_set_dcbx_app(softc, app, true); + + if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) + rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, true); + + return rc; +} + +int +bnxt_dcb_ieee_delapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app) +{ + int rc; + + if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || + !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) + return -EINVAL; + + rc = bnxt_dcb_ieee_dscp_app_prep(softc, app); + if (rc) + return rc; + + if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE && + app->protocol == ETH_P_ROCE) || + (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM && + app->protocol == ROCE_V2_UDP_DPORT)) + rc = bnxt_hwrm_set_dcbx_app(softc, app, false); + + if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) + rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, false); + + return rc; +} + +int +bnxt_dcb_ieee_listapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app, + size_t nitems, int *num_inputs) +{ + bnxt_hwrm_get_dcbx_app(softc, app, nitems, num_inputs); + bnxt_hwrm_queue_dscp2pri_qcfg(softc, app, nitems, num_inputs); + + return 0; +} + +uint8_t +bnxt_dcb_getdcbx(struct bnxt_softc *softc) +{ + return softc->dcbx_cap; +} + +uint8_t +bnxt_dcb_setdcbx(struct bnxt_softc *softc, uint8_t mode) +{ + /* All firmware DCBX settings are set in NVRAM */ + if (softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED) + return 1; + + /* + * Do't allow editing CAP_DCBX_LLD_MANAGED since it is driven + * based on FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED + */ + if ((softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED) != + (mode & BNXT_DCB_CAP_DCBX_LLD_MANAGED)) + return 1; + + if (mode & BNXT_DCB_CAP_DCBX_HOST) { + if (BNXT_VF(softc) || (softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) + return 1; + + /* only support BNXT_IEEE */ + if ((mode & BNXT_DCB_CAP_DCBX_VER_CEE) || + !(mode & BNXT_DCB_CAP_DCBX_VER_IEEE)) + return 1; + } + + if (mode == softc->dcbx_cap) + return 0; + + softc->dcbx_cap = mode; + return 0; +} + +void +bnxt_dcb_init(struct bnxt_softc *softc) +{ + struct bnxt_ieee_ets ets = {0}; + struct bnxt_ieee_pfc pfc = {0}; + + softc->dcbx_cap = 0; + + if (softc->hwrm_spec_code < 0x10501) + return; + + softc->ieee_ets = malloc(sizeof(struct bnxt_ieee_ets), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->ieee_ets) + return; + + softc->ieee_pfc = malloc(sizeof(struct bnxt_ieee_pfc), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->ieee_pfc) + return; + + bnxt_hwrm_queue_dscp_qcaps(softc); + softc->dcbx_cap = BNXT_DCB_CAP_DCBX_VER_IEEE; + if (BNXT_PF(softc) && !(softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) + softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_HOST; + else if (softc->fw_cap & BNXT_FW_CAP_DCBX_AGENT) + softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_LLD_MANAGED; + + bnxt_dcb_ieee_setets(softc, &ets); + bnxt_dcb_ieee_setpfc(softc, &pfc); + +} + +void +bnxt_dcb_free(struct bnxt_softc *softc) +{ + free(softc->ieee_ets, M_DEVBUF); + softc->ieee_ets = NULL; + free(softc->ieee_pfc, M_DEVBUF); + softc->ieee_pfc = NULL; +} diff --git a/sys/dev/bnxt/bnxt_en/bnxt_dcb.h b/sys/dev/bnxt/bnxt_en/bnxt_dcb.h new file mode 100644 index 000000000000..fa68401583ca --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.h @@ -0,0 +1,131 @@ +/*- + * 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_DCB_H +#define _BNXT_DCB_H + +#define BNXT_IEEE_8021QAZ_MAX_TCS 8 +#define BNXT_IEEE_8021QAZ_TSA_STRICT 0 +#define BNXT_IEEE_8021QAZ_TSA_ETS 2 +#define BNXT_IEEE_8021QAZ_TSA_VENDOR 255 + +#define BNXT_DCB_CAP_DCBX_HOST 0x01 +#define BNXT_DCB_CAP_DCBX_LLD_MANAGED 0x02 +#define BNXT_DCB_CAP_DCBX_VER_CEE 0x04 +#define BNXT_DCB_CAP_DCBX_VER_IEEE 0x08 +#define BNXT_DCB_CAP_DCBX_STATIC 0x10 + +#ifndef __struct_group +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } +#endif +#ifndef struct_group_attr +#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ + __struct_group(/* no tag */, NAME, ATTRS, MEMBERS) +#endif + +struct bnxt_cos2bw_cfg { + uint8_t pad[3]; + struct_group_attr(cfg, __packed, + uint8_t queue_id; + uint32_t min_bw; + uint32_t max_bw; +#define BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29) + uint8_t tsa; + uint8_t pri_lvl; + uint8_t bw_weight; + ); + uint8_t unused; +}; + +struct bnxt_dscp2pri_entry { + uint8_t dscp; + uint8_t mask; + uint8_t pri; +}; + +struct bnxt_ieee_ets { + uint8_t willing; + uint8_t ets_cap; + uint8_t cbs; + uint8_t tc_tx_bw[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t tc_rx_bw[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t tc_tsa[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t prio_tc[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t tc_reco_bw[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t tc_reco_tsa[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint8_t reco_prio_tc[BNXT_IEEE_8021QAZ_MAX_TCS]; +} __attribute__ ((__packed__)); + +struct bnxt_ieee_pfc { + uint8_t pfc_cap; + uint8_t pfc_en; + uint8_t mbc; + uint16_t delay; + uint64_t requests[BNXT_IEEE_8021QAZ_MAX_TCS]; + uint64_t indications[BNXT_IEEE_8021QAZ_MAX_TCS]; +} __attribute__ ((__packed__)); + +struct bnxt_dcb_app { + uint8_t selector; + uint8_t priority; + uint16_t protocol; +} __attribute__ ((__packed__)); + +struct bnxt_eee { + uint32_t cmd; + uint32_t supported; + uint32_t advertised; + uint32_t lp_advertised; + uint32_t eee_active; + uint32_t eee_enabled; + uint32_t tx_lpi_enabled; + uint32_t tx_lpi_timer; + uint32_t reserved[2]; +} __attribute__ ((__packed__)); + +#define BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE 1 +#define BNXT_IEEE_8021QAZ_APP_SEL_STREAM 2 +#define BNXT_IEEE_8021QAZ_APP_SEL_DGRAM 3 +#define BNXT_IEEE_8021QAZ_APP_SEL_ANY 4 +#define BNXT_IEEE_8021QAZ_APP_SEL_DSCP 5 +#define ETH_P_ROCE 0x8915 +#define ROCE_V2_UDP_DPORT 4791 + +#define BNXT_LLQ(q_profile) \ + ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE || \ + (q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_NIC) +#define BNXT_CNPQ(q_profile) \ + ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP) + +#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300 + +#endif diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c index 37238b857ef5..7dd555cfaadb 100644 --- a/sys/dev/bnxt/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" @@ -42,13 +43,42 @@ static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req); static void bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req); -static int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t); -static int hwrm_send_message(struct bnxt_softc *, void *, uint32_t); -static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t); /* NVRam stuff has a five minute timeout */ #define BNXT_NVM_TIMEO (5 * 60 * 1000) +#define BNXT_RX_STATS_PRI_ENTRY(counter, n) \ + BNXT_RX_STATS_EXT_OFFSET(counter##_cos0) + +#define BNXT_TX_STATS_PRI_ENTRY(counter, n) \ + BNXT_TX_STATS_EXT_OFFSET(counter##_cos0) + +#define BNXT_RX_STATS_PRI_ENTRIES(counter) \ + BNXT_RX_STATS_PRI_ENTRY(counter, 0), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 1), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 2), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 3), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 4), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 5), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 6), \ + BNXT_RX_STATS_PRI_ENTRY(counter, 7) + +#define BNXT_TX_STATS_PRI_ENTRIES(counter) \ + BNXT_TX_STATS_PRI_ENTRY(counter, 0), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 1), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 2), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 3), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 4), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 5), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 6), \ + BNXT_TX_STATS_PRI_ENTRY(counter, 7) + + +long bnxt_rx_bytes_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_bytes)}; +long bnxt_rx_pkts_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_packets)}; +long bnxt_tx_bytes_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_bytes)}; +long bnxt_tx_pkts_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_packets)}; + static int bnxt_hwrm_err_map(uint16_t err) { @@ -97,7 +127,7 @@ bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc) return; } -static void +void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request, uint16_t req_type) { @@ -109,7 +139,7 @@ bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request, req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr); } -static int +int _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) { struct input *req = msg; @@ -125,6 +155,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; @@ -222,7 +256,7 @@ _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) return 0; } -static int +int hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) { int rc; @@ -234,13 +268,16 @@ hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) } int -bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc) +bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc, uint32_t path_dir) { int rc = 0; struct hwrm_queue_qportcfg_input req = {0}; struct hwrm_queue_qportcfg_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; - uint8_t i, j, *qptr; + uint8_t max_tc, max_lltc, *max_q; + uint8_t queue_profile, queue_id; + struct bnxt_queue_info *q_info; + uint8_t i, j, *qptr, *q_ids; bool no_rdma; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG); @@ -254,29 +291,56 @@ bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc) rc = -EINVAL; goto qportcfg_exit; } - softc->max_tc = resp->max_configurable_queues; - 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; + if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG) { + softc->is_asym_q = true; + /* bnxt_init_cosq_names(softc, path_dir); */ + } else { + softc->is_asym_q = false; + /* bnxt_free_stats_cosqnames_mem(softc); */ + } + + max_tc = min_t(uint8_t, resp->max_configurable_queues, BNXT_MAX_QUEUE); + max_lltc = resp->max_configurable_lossless_queues; + /* + * No RDMA support yet. + * no_rdma = !(softc->flags & BNXT_FLAG_ROCE_CAP); + */ + no_rdma = true; qptr = &resp->queue_id0; - 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++; + + if (path_dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX) { + q_info = softc->tx_q_info; + q_ids = softc->tx_q_ids; + max_q = &softc->tx_max_q; + } else { + q_info = softc->rx_q_info; + q_ids = softc->rx_q_ids; + max_q = &softc->rx_max_q; + } + + for (i = 0, j = 0; i < max_tc; i++) { + queue_id = *qptr; + qptr++; + + queue_profile = *qptr; + qptr++; + + q_info[j].queue_id = queue_id; + q_info[j].queue_profile = queue_profile; + q_ids[i] = queue_id; + softc->tc_to_qidx[j] = j; - if (!BNXT_CNPQ(softc->q_info[j].profile) || - (no_rdma && BNXT_PF(softc))) + + if (!BNXT_CNPQ(q_info[j].queue_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; + *max_q = max_tc; + max_tc = max_t(uint8_t, j, 1); + softc->max_tc = softc->max_tc ? min(softc->max_tc, max_tc) : max_tc; + softc->max_lltc = softc->max_lltc ? min(softc->max_lltc, max_lltc) : max_lltc; if (softc->max_lltc > softc->max_tc) softc->max_lltc = softc->max_tc; @@ -286,6 +350,102 @@ qportcfg_exit: return rc; } +static int bnxt_alloc_all_ctx_pg_info(struct bnxt_softc *softc, int ctx_max) +{ + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + u16 type; + + for (type = 0; type < 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_ATOMIC); + 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; +} + +#define BNXT_CTX_INIT_VALID(flags) \ + (!!((flags) & \ + HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_ENABLE_CTX_KIND_INIT)) + +static int +bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt_softc *softc) +{ + struct hwrm_func_backing_store_qcaps_v2_input req = {0}; + struct hwrm_func_backing_store_qcaps_v2_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct bnxt_ctx_mem_info *ctx = NULL; + u16 type; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS_V2); + + ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!ctx) + return -ENOMEM; + + softc->ctx_mem = ctx; + + BNXT_HWRM_LOCK(softc); + for (type = 0; type < BNXT_CTX_V2_MAX; ) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + u8 init_val, init_off, i; + __le32 *p; + u32 flags; + + req.type = cpu_to_le16(type); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto ctx_done; + flags = le32_to_cpu(resp->flags); + type = le16_to_cpu(resp->next_valid_type); + if (!(flags & HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_TYPE_VALID)) + continue; + + ctxm->type = le16_to_cpu(resp->type); + ctxm->flags = flags; + + ctxm->entry_size = le16_to_cpu(resp->entry_size); + ctxm->instance_bmap = le32_to_cpu(resp->instance_bit_map); + ctxm->entry_multiple = resp->entry_multiple; + ctxm->max_entries = le32_to_cpu(resp->max_num_entries); + ctxm->min_entries = le32_to_cpu(resp->min_num_entries); + init_val = resp->ctx_init_value; + init_off = resp->ctx_init_offset; + bnxt_init_ctx_initializer(ctxm, init_val, init_off, + BNXT_CTX_INIT_VALID(flags)); + ctxm->split_entry_cnt = min_t(u8, resp->subtype_valid_cnt, + BNXT_MAX_SPLIT_ENTRY); + for (i = 0, p = &resp->split_entry_0; i < ctxm->split_entry_cnt; + i++, p++) + ctxm->split[i] = le32_to_cpu(*p); + } + rc = bnxt_alloc_all_ctx_pg_info(softc, BNXT_CTX_V2_MAX); + +ctx_done: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc) { struct hwrm_func_backing_store_qcaps_input req = {0}; @@ -293,63 +453,115 @@ 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_CHIP_P7(softc)) { + if (softc->fw_cap & BNXT_FW_CAP_BACKING_STORE_V2) + return bnxt_hwrm_func_backing_store_qcaps_v2(softc); + } + + 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->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->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, BNXT_CTX_MAX); } else { rc = 0; } @@ -368,14 +580,11 @@ ctx_err: 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 (!rmem->nr_pages) + return; - if (BNXT_PAGE_SHIFT == 13) - pg_size = 1 << 4; - else if (BNXT_PAGE_SIZE == 16) - pg_size = 2 << 4; + BNXT_SET_CTX_PAGE_ATTR(*pg_attr); - *pg_attr = pg_size; if (rmem->depth >= 1) { if (rmem->depth == 2) *pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2; @@ -392,150 +601,216 @@ 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); - req.tim_entry_size = htole16(ctx->tim_entry_size); + ctxm = &ctx->ctx_arr[BNXT_CTX_TIM]; + ctx_pg = ctxm->pg_info; + req.tim_num_entries = cpu_to_le32(ctx_pg->entries); + req.tim_entry_size = cpu_to_le16(ctxm->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); + ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC]; + ctx_pg = ctxm->pg_info; + req.vnic_num_vnic_entries = cpu_to_le16(ctxm->vnic_entries); req.vnic_num_ring_table_entries = - htole16(ctx->vnic_max_ring_table_entries); - req.vnic_entry_size = htole16(ctx->vnic_entry_size); + cpu_to_le16(ctxm->max_entries - ctxm->vnic_entries); + req.vnic_entry_size = cpu_to_le16(ctxm->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); + ctxm = &ctx->ctx_arr[BNXT_CTX_STAT]; + ctx_pg = ctxm->pg_info; + req.stat_num_entries = cpu_to_le32(ctxm->max_entries); + req.stat_entry_size = cpu_to_le16(ctxm->entry_size); bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, &req.stat_pg_size_stat_lvl, &req.stat_page_dir); } + ctxm = &ctx->ctx_arr[BNXT_CTX_STQM]; 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) { + ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP, + ctx_pg = ctxm->pg_info; + i < BNXT_MAX_TQM_LEGACY_RINGS; + ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[i], + 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); + req.tqm_entry_size = cpu_to_le16(ctxm->entry_size); + *num_entries = cpu_to_le32(ctx_pg->entries); bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir); } - - if (req_len > softc->hwrm_max_ext_req_len) - req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN; - - rc = hwrm_send_message(softc, &req, req_len); - if (rc) - rc = -EIO; - return rc; + if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_RING8) { + pg_attr = &req.tqm_ring8_pg_size_tqm_ring_lvl; + pg_dir = &req.tqm_ring8_page_dir; + ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[8]; + req.tqm_ring8_num_entries = cpu_to_le32(ctx_pg->entries); + bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir); + } + req.flags = cpu_to_le32(flags); + return hwrm_send_message(softc, &req, sizeof(req)); } int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all) { - struct hwrm_func_resource_qcaps_output *resp = + 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; + 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_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); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) { + rc = -EIO; + goto hwrm_func_resc_qcaps_exit; + } - if (BNXT_CHIP_P5(softc)) { - hw_resc->max_nqs = le16toh(resp->max_msix); - hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings; - } + 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_PLUS(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; + return rc; +} + +int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt_softc *softc, + struct bnxt_ctx_mem_type *ctxm, + bool last) +{ + struct hwrm_func_backing_store_cfg_v2_input req = {0}; + u32 instance_bmap = ctxm->instance_bmap; + int i, j, rc = 0, n = 1; + __le32 *p; + + if (!(ctxm->flags & BNXT_CTX_MEM_TYPE_VALID) || !ctxm->pg_info) + return 0; + + if (instance_bmap) + n = hweight32(ctxm->instance_bmap); + else + instance_bmap = 1; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG_V2); + + BNXT_HWRM_LOCK(softc); + req.type = cpu_to_le16(ctxm->type); + req.entry_size = cpu_to_le16(ctxm->entry_size); + req.subtype_valid_cnt = ctxm->split_entry_cnt; + for (i = 0, p = &req.split_entry_0; i < ctxm->split_entry_cnt; i++) + p[i] = cpu_to_le32(ctxm->split[i]); + for (i = 0, j = 0; j < n && !rc; i++) { + struct bnxt_ctx_pg_info *ctx_pg; + + if (!(instance_bmap & (1 << i))) + continue; + req.instance = cpu_to_le16(i); + ctx_pg = &ctxm->pg_info[j++]; + if (!ctx_pg->entries) + continue; + req.num_entries = cpu_to_le32(ctx_pg->entries); + bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, + &req.page_size_pbl_level, + &req.page_dir); + if (last && j == n) + req.flags = + cpu_to_le32(HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_FLAGS_BS_CFG_ALL_DONE); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + } + BNXT_HWRM_UNLOCK(softc); + return rc; } int @@ -599,8 +874,6 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b; softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b; softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b; - snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d", - resp->hwrm_fw_major, resp->hwrm_fw_minor, resp->hwrm_fw_build); strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR, BNXT_VERSTR_SIZE); strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name, @@ -622,9 +895,9 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE); } else { - snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE, - "%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor, - resp->mgmt_fw_build); + snprintf(softc->ver_info->mgmt_fw_ver, FW_VER_STR_LEN, + "%d.%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor, + resp->mgmt_fw_build, resp->mgmt_fw_patch); strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name, BNXT_NAME_SIZE); } @@ -636,9 +909,9 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) BNXT_NAME_SIZE); } else { - snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE, - "%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor, - resp->netctrl_fw_build); + snprintf(softc->ver_info->netctrl_fw_ver, FW_VER_STR_LEN, + "%d.%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor, + resp->netctrl_fw_build, resp->netctrl_fw_patch); strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name, BNXT_NAME_SIZE); } @@ -649,8 +922,8 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) } else { snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE, - "%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor, - resp->roce_fw_build); + "%d.%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor, + resp->roce_fw_build, resp->roce_fw_patch); strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name, BNXT_NAME_SIZE); } @@ -669,6 +942,7 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) len = BC_HWRM_STR_LEN; } + softc->ver_info->fw_ver_code = BNXT_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv); snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d", fw_maj, fw_min, fw_bld, fw_rsv); @@ -678,6 +952,7 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) snprintf(softc->ver_info->fw_ver_str + fw_ver_len, FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s", resp->active_pkg_name); + softc->fw_cap |= BNXT_FW_CAP_PKG_VER; } softc->ver_info->chip_num = le16toh(resp->chip_num); @@ -690,38 +965,135 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) softc->hwrm_max_req_len = le16toh(resp->max_req_win_len); 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) && (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED)) softc->flags |= BNXT_FLAG_SHORT_CMD; + if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) && + (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED)) + softc->fw_cap |= BNXT_FW_CAP_SHORT_CMD; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_KONG_MB_CHNL; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_TRUSTED_VF; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_CFA_ADV_FLOW; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_EEM_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_CFA_EEM; + + if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_TRUFLOW_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_TRUFLOW_EN; + fail: BNXT_HWRM_UNLOCK(softc); return rc; } -int -bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc) -{ +static const u16 bnxt_async_events_arr[] = { + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFERRED_RESPONSE, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE, +}; + +int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *bp, unsigned long *bmap, int bmap_size, + bool async_only) +{ + DECLARE_BITMAP(async_events_bmap, 256); + u32 *events = (u32 *)async_events_bmap; + struct hwrm_func_drv_rgtr_output *resp = + (void *)bp->hwrm_cmd_resp.idi_vaddr; struct hwrm_func_drv_rgtr_input req = {0}; + u32 flags = 0; + int rc; + int i; - bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR); - - req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER | - HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE); + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR); + req.ver_maj = HWRM_VERSION_MAJOR; + req.ver_min = HWRM_VERSION_MINOR; + req.ver_upd = HWRM_VERSION_UPDATE; + + req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE | + HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER | + HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD); + + if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET) + flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT; + if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) + flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT | + HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_MASTER_SUPPORT; + if (bp->fw_cap & BNXT_FW_CAP_NPAR_1_2) + flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_NPAR_1_2_SUPPORT; + flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ASYM_QUEUE_CFG_SUPPORT; + req.flags = htole32(flags); req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD); - req.ver_maj = __FreeBSD_version / 100000; - req.ver_min = (__FreeBSD_version / 1000) % 100; - req.ver_upd = (__FreeBSD_version / 100) % 10; + if (BNXT_PF(bp)) { + req.enables |= + htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD); + } - return hwrm_send_message(softc, &req, sizeof(req)); + if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE) + req.flags |= cpu_to_le32(HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FLOW_HANDLE_64BIT_MODE); + + memset(async_events_bmap, 0, sizeof(async_events_bmap)); + for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++) { + u16 event_id = bnxt_async_events_arr[i]; + + if (event_id == HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY && + !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) { + continue; + } + __set_bit(bnxt_async_events_arr[i], async_events_bmap); + } + if (bmap && bmap_size) { + for (i = 0; i < bmap_size; i++) { + if (test_bit(i, bmap)) + __set_bit(i, async_events_bmap); + } + } + for (i = 0; i < 8; i++) + req.async_event_fwd[i] |= htole32(events[i]); + + if (async_only) + req.enables = + htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD); + + rc = hwrm_send_message(bp, &req, sizeof(req)); + + if (!rc) { + if (resp->flags & + le32toh(HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED)) + bp->fw_cap |= BNXT_FW_CAP_IF_CHANGE; + } + + + return rc; } int @@ -766,6 +1138,7 @@ bnxt_hwrm_func_qcaps(struct bnxt_softc *softc) struct hwrm_func_qcaps_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; struct bnxt_func_info *func = &softc->func; + uint32_t flags, flags_ext, flags_ext2; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS); req.fid = htole16(0xffff); @@ -775,13 +1148,78 @@ bnxt_hwrm_func_qcaps(struct bnxt_softc *softc) if (rc) goto fail; - if (resp->flags & - htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED)) + flags = htole32(resp->flags); + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED) softc->flags |= BNXT_FLAG_WOL_CAP; - if (resp->flags & - htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)) + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED) softc->flags |= BNXT_FLAG_FW_CAP_EXT_STATS; + /* Enable RoCE only on Thor devices */ + if (BNXT_CHIP_P5_PLUS(softc)) { + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V1_SUPPORTED) + softc->flags |= BNXT_FLAG_ROCEV1_CAP; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V2_SUPPORTED) + softc->flags |= BNXT_FLAG_ROCEV2_CAP; + } + + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_LINK_ADMIN_STATUS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_LINK_ADMIN; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ADMIN_PF_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_ADMIN_PF; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_HOT_RESET_CAPABLE) + softc->fw_cap |= BNXT_FW_CAP_HOT_RESET; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE) + softc->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PCIE_STATS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERR_RECOVER_RELOAD) + softc->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_NOTIFY_VF_DEF_VNIC_CHNG_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_VF_VNIC_NOTIFY; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_CRASHDUMP_CMD_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_CRASHDUMP; + if (!(flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_VLAN_ACCELERATION_TX_DISABLED)) + softc->fw_cap |= BNXT_FW_CAP_VLAN_TX_INSERT; + if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_DBG_QCAPS_CMD_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_DBG_QCAPS; + + flags_ext = htole32(resp->flags_ext); + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_EXT_HW_STATS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED; + if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_ECN_STATS_SUPPORTED)) + softc->fw_cap |= BNXT_FW_CAP_ECN_STATS; + + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PPS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_PTP_PPS; + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PTM_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_PTP_PTM; + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_64BIT_RTC_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_PTP_RTC; + if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_HOT_RESET_IF_SUPPORT)) + softc->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF; + if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED)) + softc->fw_cap |= BNXT_FW_CAP_LIVEPATCH; + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_NPAR_1_2_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_NPAR_1_2; + if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_BS_V2_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_BACKING_STORE_V2; + if (BNXT_PF(softc) && + (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_VF_CFG_ASYNC_FOR_PF_SUPPORTED)) + softc->fw_cap |= BNXT_FW_CAP_VF_CFG_FOR_PF; + + flags_ext2 = htole32(resp->flags_ext2); + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_RX_ALL_PKTS_TIMESTAMPS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_RX_ALL_PKT_TS; + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_DBR_DROP_RECOVERY_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_DBR_SUPPORTED; + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DBR_PACING_EXT_SUPPORTED || + flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_DBR_PACING_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_DBR_PACING_SUPPORTED; + + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_GENERIC_STATS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_GENERIC_STATS; func->fw_fid = le16toh(resp->fid); memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN); func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx); @@ -820,26 +1258,75 @@ fail: int bnxt_hwrm_func_qcfg(struct bnxt_softc *softc) { - struct hwrm_func_qcfg_input req = {0}; - struct hwrm_func_qcfg_output *resp = - (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_func_qcfg_input req = {0}; + struct hwrm_func_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg; - int rc; + uint32_t min_db_offset = 0; + uint16_t flags; + int rc; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG); - req.fid = htole16(0xffff); + req.fid = htole16(0xffff); BNXT_HWRM_LOCK(softc); rc = _hwrm_send_message(softc, &req, sizeof(req)); - if (rc) - goto fail; + if (rc) + goto end; fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings); fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings); fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings); fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics); -fail: + + switch (resp->port_partition_type) { + case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0: + case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_2: + case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5: + case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0: + softc->port_partition_type = resp->port_partition_type; + break; + } + + flags = le16toh(resp->flags); + if (flags & (HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED | + HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_LLDP_AGENT_ENABLED)) { + softc->fw_cap |= BNXT_FW_CAP_LLDP_AGENT; + if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED) + softc->fw_cap |= BNXT_FW_CAP_DCBX_AGENT; + } + if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_HOST)) + softc->flags |= BNXT_FLAG_MULTI_HOST; + if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_ROOT)) + softc->flags |= BNXT_FLAG_MULTI_ROOT; + if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_SECURE_MODE_ENABLED) + softc->fw_cap |= BNXT_FW_CAP_SECURE_MODE; + if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_RING_MONITOR_ENABLED) + softc->fw_cap |= BNXT_FW_CAP_RING_MONITOR; + if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_ENABLE_RDMA_SRIOV) + softc->fw_cap |= BNXT_FW_CAP_ENABLE_RDMA_SRIOV; + + if (softc->db_size) + goto end; + + softc->legacy_db_size = le16_to_cpu(resp->legacy_l2_db_size_kb) * 1024; + + if (BNXT_CHIP_P5(softc)) { + if (BNXT_PF(softc)) + min_db_offset = DB_PF_OFFSET_P5; + else + min_db_offset = DB_VF_OFFSET_P5; + softc->legacy_db_size = min_db_offset; + } + + softc->db_size = roundup2(le16_to_cpu(resp->l2_doorbell_bar_size_kb) * + 1024, PAGE_SIZE); + if (!softc->db_size || softc->db_size > pci_resource_len(softc->pdev, 2) || + softc->db_size <= min_db_offset) + softc->db_size = pci_resource_len(softc->pdev, 2); + + end: BNXT_HWRM_UNLOCK(softc); - return rc; + return rc; } int @@ -882,15 +1369,24 @@ bnxt_hwrm_set_link_common(struct bnxt_softc *softc, req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG); } else { - req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE); - if (link_info->force_pam4_speed_set_by_user) { + if (link_info->force_speed2_nrz || + link_info->force_pam4_56_speed2 || + link_info->force_pam4_112_speed2) { + req->force_link_speeds2 = htole16(fw_link_speed); + req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_LINK_SPEEDS2); + link_info->force_speed2_nrz = false; + link_info->force_pam4_56_speed2 = false; + link_info->force_pam4_112_speed2 = false; + } else if (link_info->force_pam4_speed) { req->force_pam4_link_speed = htole16(fw_link_speed); req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED); - link_info->force_pam4_speed_set_by_user = false; + link_info->force_pam4_speed = false; } else { req->force_link_speed = htole16(fw_link_speed); } + + req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE); } /* tell chimp that the setting takes effect immediately */ @@ -1000,21 +1496,14 @@ bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause, int bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) { - struct hwrm_vnic_plcmodes_cfg_input req = {0}; + struct hwrm_vnic_plcmodes_cfg_input req = {0}; - if (!BNXT_CHIP_P5(softc)) + if (!BNXT_CHIP_P5_PLUS(softc)) return 0; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG); - /* - * TBD -- Explore these flags - * 1. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 - * 2. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6 - * 3. req.jumbo_thresh - * 4. req.hds_threshold - */ - req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT); + req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT); req.vnic_id = htole16(vnic->id); return hwrm_send_message(softc, &req, sizeof(req)); @@ -1033,7 +1522,7 @@ 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); - if (BNXT_CHIP_P5 (softc)) { + if (BNXT_CHIP_P5_PLUS (softc)) { req.default_rx_ring_id = htole16(softc->rx_rings[0].phys_id); req.default_cmpl_ring_id = @@ -1173,7 +1662,7 @@ bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp) return EDOOFUS; } - if (BNXT_CHIP_P5 (softc)) + if (BNXT_CHIP_P5_PLUS (softc)) return 0; resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; @@ -1204,7 +1693,7 @@ bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp) if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE) return 0; - if (BNXT_CHIP_P5 (softc)) + if (BNXT_CHIP_P5_PLUS (softc)) return 0; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE); @@ -1282,48 +1771,48 @@ bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, req.length = htole32(ring->ring_size); switch (type) { - case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX: + 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); + 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.queue_id = htole16(softc->tx_q_info[0].queue_id); - req.stat_ctx_id = htole32(cp_ring->stats_ctx_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; + case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX: + if (!BNXT_CHIP_P5_PLUS(softc)) break; cp_ring = &softc->rx_cp_rings[idx]; - req.stat_ctx_id = htole32(cp_ring->stats_ctx_id); + req.stat_ctx_id = htole32(cp_ring->stats_ctx_id); req.rx_buf_size = htole16(softc->rx_buf_size); - req.enables |= htole32( + 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; + case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG: + if (!BNXT_CHIP_P5_PLUS(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.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->rx_buf_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; + 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_PLUS(softc)) { + req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; break; } @@ -1331,14 +1820,15 @@ bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, 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; - } + break; + case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ: + req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; + break; + default: + device_printf(softc->dev, + "hwrm alloc invalid ring type %d\n", type); + return -1; + } BNXT_HWRM_LOCK(softc); rc = _hwrm_send_message(softc, &req, sizeof(req)); @@ -1395,7 +1885,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)) + + if (BNXT_CHIP_P7(softc)) + req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext)); + else 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)); @@ -1431,25 +1924,142 @@ bnxt_hwrm_port_qstats(struct bnxt_softc *softc) return rc; } +static int bnxt_hwrm_pri2cos_idx(struct bnxt_softc *softc, uint32_t path_dir) +{ + struct hwrm_queue_pri2cos_qcfg_input req = {0}; + struct hwrm_queue_pri2cos_qcfg_output *resp; + uint8_t *pri2cos_idx, *q_ids, max_q; + int rc, i, j; + uint8_t *pri2cos; -void + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG); + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + + req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN | + path_dir); + rc = hwrm_send_message(softc, &req, sizeof(req)); + + if (rc) + return rc; + + if (path_dir == HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX) { + pri2cos_idx = softc->tx_pri2cos_idx; + q_ids = softc->tx_q_ids; + max_q = softc->tx_max_q; + } else { + pri2cos_idx = softc->rx_pri2cos_idx; + q_ids = softc->rx_q_ids; + max_q = softc->rx_max_q; + } + + pri2cos = &resp->pri0_cos_queue_id; + + for (i = 0; i < BNXT_MAX_QUEUE; i++) { + uint8_t queue_id = pri2cos[i]; + uint8_t queue_idx; + + /* Per port queue IDs start from 0, 10, 20, etc */ + queue_idx = queue_id % 10; + if (queue_idx > BNXT_MAX_QUEUE) { + softc->pri2cos_valid = false; + rc = -EINVAL; + return rc; + } + + for (j = 0; j < max_q; j++) { + if (q_ids[j] == queue_id) + pri2cos_idx[i] = queue_idx; + } + } + + softc->pri2cos_valid = true; + + return rc; +} + +int bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc) { struct hwrm_port_qstats_ext_input req = {0}; + struct hwrm_port_qstats_ext_output *resp; + int rc = 0, i; + uint32_t tx_stat_size; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS_EXT); + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + tx_stat_size = sizeof(struct tx_port_stats_ext); req.port_id = htole16(softc->pf.port_id); - req.tx_stat_size = htole16(sizeof(struct tx_port_stats_ext)); + req.tx_stat_size = htole16(tx_stat_size); req.rx_stat_size = htole16(sizeof(struct rx_port_stats_ext)); req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats_ext.idi_paddr); req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats_ext.idi_paddr); - BNXT_HWRM_LOCK(softc); - _hwrm_send_message(softc, &req, sizeof(req)); - BNXT_HWRM_UNLOCK(softc); + rc = hwrm_send_message(softc, &req, sizeof(req)); - return; + if (!rc) { + softc->fw_rx_stats_ext_size = + le16toh(resp->rx_stat_size) / 8; + if (BNXT_FW_MAJ(softc) < 220 && !BNXT_CHIP_P7(softc) && + softc->fw_rx_stats_ext_size > BNXT_RX_STATS_EXT_NUM_LEGACY) + softc->fw_rx_stats_ext_size = BNXT_RX_STATS_EXT_NUM_LEGACY; + + softc->fw_tx_stats_ext_size = tx_stat_size ? + le16toh(resp->tx_stat_size) / 8 : 0; + } else { + softc->fw_rx_stats_ext_size = 0; + softc->fw_tx_stats_ext_size = 0; + } + + if (softc->fw_tx_stats_ext_size <= + offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) { + softc->pri2cos_valid = false; + return rc; + } + + rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX); + if (rc) + return rc; + + if (softc->is_asym_q) { + rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX); + if (rc) + return rc; + } else { + memcpy(softc->rx_pri2cos_idx, softc->tx_pri2cos_idx, sizeof(softc->rx_pri2cos_idx)); + } + + u64 *rx_port_stats_ext = (u64 *)softc->hw_rx_port_stats_ext.idi_vaddr; + u64 *tx_port_stats_ext = (u64 *)softc->hw_tx_port_stats_ext.idi_vaddr; + + if (softc->pri2cos_valid) { + for (i = 0; i < 8; i++) { + long n = bnxt_rx_bytes_pri_arr_base_off[i] + + softc->rx_pri2cos_idx[i]; + + softc->rx_bytes_pri[i] = *(rx_port_stats_ext + n); + } + for (i = 0; i < 8; i++) { + long n = bnxt_rx_pkts_pri_arr_base_off[i] + + softc->rx_pri2cos_idx[i]; + + softc->rx_packets_pri[i] = *(rx_port_stats_ext + n); + } + for (i = 0; i < 8; i++) { + long n = bnxt_tx_bytes_pri_arr_base_off[i] + + softc->tx_pri2cos_idx[i]; + + softc->tx_bytes_pri[i] = *(tx_port_stats_ext + n); + } + for (i = 0; i < 8; i++) { + long n = bnxt_tx_pkts_pri_arr_base_off[i] + + softc->tx_pri2cos_idx[i]; + + softc->tx_packets_pri[i] = *(tx_port_stats_ext + n); + } + } + + return rc; } int @@ -1594,12 +2204,15 @@ bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic, bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG); + if (BNXT_CHIP_P7(softc)) + req.flags |= HWRM_VNIC_RSS_CFG_INPUT_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT; + req.hash_type = htole32(hash_type); req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr); req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr); req.rss_ctx_idx = htole16(vnic->rss_id); req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT; - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { req.vnic_id = htole16(vnic->id); req.ring_table_pair_index = 0x0; } @@ -1646,7 +2259,7 @@ bnxt_cfg_async_cr(struct bnxt_softc *softc) req.fid = htole16(0xffff); req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id); else req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id); @@ -2231,7 +2844,7 @@ int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *softc, uint16_t i2c_addr HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET : 0) | (bank_sel_en ? HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_BANK_NUMBER : 0)); - rc = hwrm_send_message(softc, &req, sizeof(req)); + rc = _hwrm_send_message(softc, &req, sizeof(req)); if (!rc) memcpy(buf + byte_offset, output->data, xfer_size); byte_offset += xfer_size; @@ -2251,9 +2864,9 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) (void *)softc->hwrm_cmd_resp.idi_vaddr; int rc = 0; - BNXT_HWRM_LOCK(softc); bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG); + BNXT_HWRM_LOCK(softc); rc = _hwrm_send_message(softc, &req, sizeof(req)); if (rc) goto exit; @@ -2331,6 +2944,10 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) if (softc->hwrm_spec_code >= 0x10504) link_info->active_fec_sig_mode = resp->active_fec_signal_mode; + link_info->support_speeds2 = le16toh(resp->support_speeds2); + link_info->auto_link_speeds2 = le16toh(resp->auto_link_speeds2); + link_info->force_link_speeds2 = le16toh(resp->force_link_speeds2); + exit: BNXT_HWRM_UNLOCK(softc); return rc; @@ -2342,7 +2959,9 @@ bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp) if (!resp->supported_speeds_auto_mode && !resp->supported_speeds_force_mode && !resp->supported_pam4_speeds_auto_mode && - !resp->supported_pam4_speeds_force_mode) + !resp->supported_pam4_speeds_force_mode && + !resp->supported_speeds2_auto_mode && + !resp->supported_speeds2_force_mode) return true; return false; @@ -2366,6 +2985,15 @@ int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc) if (rc) goto exit; + softc->phy_flags = resp->flags | (resp->flags2 << 8); + if (resp->flags & HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EEE_SUPPORTED) { + + softc->lpi_tmr_lo = le32toh(resp->tx_lpi_timer_low) & + HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_MASK; + softc->lpi_tmr_hi = le32toh(resp->valid_tx_lpi_timer_high) & + HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_MASK; + } + if (softc->hwrm_spec_code >= 0x10a01) { if (bnxt_phy_qcaps_no_speed(resp)) { link_info->phy_state = BNXT_PHY_STATE_DISABLED; @@ -2376,6 +3004,7 @@ int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc) /* Phy re-enabled, reprobe the speeds */ link_info->support_auto_speeds = 0; link_info->support_pam4_auto_speeds = 0; + link_info->support_auto_speeds2 = 0; } } if (resp->supported_speeds_auto_mode) @@ -2391,6 +3020,14 @@ int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc) link_info->support_pam4_force_speeds = le16toh(resp->supported_pam4_speeds_force_mode); + if (resp->supported_speeds2_auto_mode) + link_info->support_auto_speeds2 = + le16toh(resp->supported_speeds2_auto_mode); + + if (resp->supported_speeds2_force_mode) + link_info->support_force_speeds2 = + le16toh(resp->supported_speeds2_force_mode); + exit: BNXT_HWRM_UNLOCK(softc); return rc; @@ -2473,120 +3110,72 @@ static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_fra int bnxt_hwrm_set_coal(struct bnxt_softc *softc) { - int i, rc = 0; - struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0}, - req_tx = {0}, *req; - uint16_t max_buf, max_buf_irq; - uint16_t buf_tmr, buf_tmr_irq; - uint32_t flags; + int i, rc = 0; + struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0}, + req_tx = {0}, *req; + uint16_t max_buf, max_buf_irq; + uint16_t buf_tmr, buf_tmr_irq; + uint32_t flags; - bnxt_hwrm_cmd_hdr_init(softc, &req_rx, - HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); - bnxt_hwrm_cmd_hdr_init(softc, &req_tx, - HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); + bnxt_hwrm_cmd_hdr_init(softc, &req_rx, + HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); + bnxt_hwrm_cmd_hdr_init(softc, &req_tx, + HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); - /* Each rx completion (2 records) should be DMAed immediately. - * DMA 1/4 of the completion buffers at a time. - */ - max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2); - /* max_buf must not be zero */ - max_buf = clamp_t(uint16_t, max_buf, 1, 63); - max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63); - buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs); - /* buf timer set to 1/4 of interrupt timer */ - buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); - buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq); - buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); - - flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; - - /* RING_IDLE generates more IRQs for lower latency. Enable it only - * if coal_usecs is less than 25 us. - */ - if (softc->rx_coal_usecs < 25) - flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE; - - bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, - buf_tmr_irq << 16 | buf_tmr, flags, &req_rx); - - /* max_buf must not be zero */ - max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63); - max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63); - buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs); - /* buf timer set to 1/4 of interrupt timer */ - buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); - buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq); - buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); - flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; - bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, - buf_tmr_irq << 16 | buf_tmr, flags, &req_tx); - - for (i = 0; i < softc->nrxqsets; i++) { + /* Each rx completion (2 records) should be DMAed immediately. + * DMA 1/4 of the completion buffers at a time. + */ + max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2); + /* max_buf must not be zero */ + max_buf = clamp_t(uint16_t, max_buf, 1, 63); + max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63); + buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs); + /* buf timer set to 1/4 of interrupt timer */ + buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); + buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq); + buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); + + flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; + + /* RING_IDLE generates more IRQs for lower latency. Enable it only + * if coal_usecs is less than 25 us. + */ + if (softc->rx_coal_usecs < 25) + flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE; + + bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, + buf_tmr_irq << 16 | buf_tmr, flags, &req_rx); + + /* max_buf must not be zero */ + max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63); + max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63); + buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs); + /* buf timer set to 1/4 of interrupt timer */ + buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); + buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq); + buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); + flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; + bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, + buf_tmr_irq << 16 | buf_tmr, flags, &req_tx); + + for (i = 0; i < softc->nrxqsets; i++) { req = &req_rx; - /* - * TBD: - * Check if Tx also needs to be done - * So far, Tx processing has been done in softirq contest - * - * req = &req_tx; - */ req->ring_id = htole16(softc->grp_info[i].cp_ring_id); - rc = hwrm_send_message(softc, req, sizeof(*req)); - if (rc) - break; - } - return rc; -} - -int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap, - int bmap_size) -{ - struct hwrm_func_drv_rgtr_input req = {0}; - bitstr_t *async_events_bmap; - uint32_t *events; - int i; - -#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); - bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE); - bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE); - - if (bmap && bmap_size) { - for (i = 0; i < bmap_size; i++) { - if (bit_test(bmap, i)) - bit_set(async_events_bmap, i); - } + rc = hwrm_send_message(softc, req, sizeof(*req)); + if (rc) + break; } - - for (i = 0; i < 8; i++) - req.async_event_fwd[i] |= htole32(events[i]); - - free(async_events_bmap, M_DEVBUF); - - return hwrm_send_message(softc, &req, sizeof(req)); + return rc; } void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type, - uint32_t ring_id, uint32_t *prod, uint32_t *cons) + uint32_t ring_id, uint32_t *prod, uint32_t *cons) { - hwrm_dbg_ring_info_get_input_t req = {0}; - hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; - int rc = 0; + hwrm_dbg_ring_info_get_input_t req = {0}; + hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc = 0; *prod = *cons = 0xffffffff; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET); diff --git a/sys/dev/bnxt/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h index 930ff424ecb8..126cad977c82 100644 --- a/sys/dev/bnxt/bnxt_hwrm.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h @@ -32,12 +32,15 @@ #define BNXT_PAUSE_TX (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) #define BNXT_PAUSE_RX (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) -#define BNXT_AUTO_PAUSE_AUTONEG_PAUSE \ - (HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE) +#define BNXT_AUTO_PAUSE_AUTONEG_PAUSE \ + (HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE) #define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input) #define BNXT_BACKING_STORE_CFG_LEGACY_LEN 256 +#define SHORT_HWRM_CMD_TIMEOUT 500 /* HWRM Function Prototypes */ +int +hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len); int bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc); void bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc); int bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, @@ -45,8 +48,9 @@ int bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t type, struct bnxt_ring *ring, int cmpl_ring_id); int bnxt_hwrm_ver_get(struct bnxt_softc *softc); -int bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc); -int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc); +int bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc, uint32_t path_dir); +int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *bp, unsigned long *bmap, int bmap_size, + bool async_only); int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown); int bnxt_hwrm_func_qcaps(struct bnxt_softc *softc); int bnxt_hwrm_func_qcfg(struct bnxt_softc *softc); @@ -64,7 +68,7 @@ int bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr, uint64_t paddr); int bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr); int bnxt_hwrm_port_qstats(struct bnxt_softc *softc); -void bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc); +int bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc); int bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp); int bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *gr); @@ -122,13 +126,19 @@ int bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc); int bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc); int bnxt_hwrm_set_coal(struct bnxt_softc *softc); int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap, - int bmap_size); + int bmap_size); int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc); int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t); +int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt_softc *softc, + struct bnxt_ctx_mem_type *ctxm, + bool last); int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all); int bnxt_hwrm_reserve_pf_rings (struct bnxt_softc *softc); void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type, - uint32_t ring_id, uint32_t *prod, uint32_t *); + uint32_t ring_id, uint32_t *prod, uint32_t *); int bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len, void *resp, uint32_t resp_len, uint32_t timeout); +int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t); +int hwrm_send_message(struct bnxt_softc *, void *, uint32_t); +void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t); #endif diff --git a/sys/dev/bnxt/bnxt_ioctl.h b/sys/dev/bnxt/bnxt_en/bnxt_ioctl.h index 370cf89f3c96..370cf89f3c96 100644 --- a/sys/dev/bnxt/bnxt_ioctl.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_ioctl.h diff --git a/sys/dev/bnxt/bnxt_mgmt.c b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c index 7185fa2f5c0a..bbc12b96d8c6 100644 --- a/sys/dev/bnxt/bnxt_mgmt.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c @@ -96,6 +96,71 @@ bnxt_mgmt_loader(struct module *m, int what, void *arg) } static int +bnxt_mgmt_process_dcb(struct cdev *dev, u_long cmd, caddr_t data, + int flag, struct thread *td) +{ + struct bnxt_softc *softc = NULL; + struct bnxt_mgmt_dcb mgmt_dcb = {}; + void *user_ptr; + int ret = 0; + + memcpy(&user_ptr, data, sizeof(user_ptr)); + if (copyin(user_ptr, &mgmt_dcb, sizeof(mgmt_dcb))) { + printf("%s: %s:%d Failed to copy data from user\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -EFAULT; + } + softc = bnxt_find_dev(mgmt_dcb.hdr.domain, mgmt_dcb.hdr.bus, + mgmt_dcb.hdr.devfn, NULL); + if (!softc) { + printf("%s: %s:%d unable to find softc reference\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -ENODEV; + } + + switch (mgmt_dcb.op) { + case BNXT_MGMT_DCB_GET_ETS: + bnxt_dcb_ieee_getets(softc, &mgmt_dcb.req.ets); + break; + case BNXT_MGMT_DCB_SET_ETS: + bnxt_dcb_ieee_setets(softc, &mgmt_dcb.req.ets); + break; + case BNXT_MGMT_DCB_GET_PFC: + bnxt_dcb_ieee_getpfc(softc, &mgmt_dcb.req.pfc); + break; + case BNXT_MGMT_DCB_SET_PFC: + bnxt_dcb_ieee_setpfc(softc, &mgmt_dcb.req.pfc); + break; + case BNXT_MGMT_DCB_SET_APP: + bnxt_dcb_ieee_setapp(softc, &mgmt_dcb.req.app_tlv.app[0]); + break; + case BNXT_MGMT_DCB_DEL_APP: + bnxt_dcb_ieee_delapp(softc, &mgmt_dcb.req.app_tlv.app[0]); + break; + case BNXT_MGMT_DCB_LIST_APP: + bnxt_dcb_ieee_listapp(softc, &mgmt_dcb.req.app_tlv.app[0], + nitems(mgmt_dcb.req.app_tlv.app), + &mgmt_dcb.req.app_tlv.num_app); + break; + default: + device_printf(softc->dev, "%s:%d Invalid op 0x%x\n", + __FUNCTION__, __LINE__, mgmt_dcb.op); + ret = -EFAULT; + goto end; + } + + if (copyout(&mgmt_dcb, user_ptr, sizeof(mgmt_dcb))) { + device_printf(softc->dev, "%s:%d Failed to copy response to user\n", + __FUNCTION__, __LINE__); + ret = -EFAULT; + goto end; + } + +end: + return ret; +} + +static int bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) { @@ -141,19 +206,7 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, } req = malloc(msg_temp.len_req, M_BNXT, M_WAITOK | M_ZERO); - if(!req) { - device_printf(softc->dev, "%s:%d Memory allocation failed", - __FUNCTION__, __LINE__); - return -ENOMEM; - } - resp = malloc(msg_temp.len_resp, M_BNXT, M_WAITOK | M_ZERO); - if(!resp) { - device_printf(softc->dev, "%s:%d Memory allocation failed", - __FUNCTION__, __LINE__); - ret = -ENOMEM; - goto end; - } if (copyin((void *)msg_temp.usr_req, req, msg_temp.len_req)) { device_printf(softc->dev, "%s:%d Failed to copy data from user\n", @@ -173,12 +226,6 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, (num_ind * sizeof(struct dma_info)); msg2 = malloc(size, M_BNXT, M_WAITOK | M_ZERO); - if(!msg2) { - device_printf(softc->dev, "%s:%d Memory allocation failed", - __FUNCTION__, __LINE__); - ret = -ENOMEM; - goto end; - } if (copyin((void *)mgmt_req.req.hreq, msg2, size)) { device_printf(softc->dev, "%s:%d Failed to copy" @@ -345,9 +392,12 @@ bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, break; case BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM: mtx_lock(&mgmt_lock); - ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td); + ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td); mtx_unlock(&mgmt_lock); break; + case BNXT_MGMT_OPCODE_DCB_OPS: + ret = bnxt_mgmt_process_dcb(dev, cmd, data, flag, td); + break; default: printf("%s: Unknown command 0x%lx\n", DRIVER_NAME, cmd); ret = -EINVAL; diff --git a/sys/dev/bnxt/bnxt_mgmt.h b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h index f130ad386809..8489a223adef 100644 --- a/sys/dev/bnxt/bnxt_mgmt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h @@ -41,6 +41,7 @@ #define BNXT_MGMT_OPCODE_GET_DEV_INFO 0x80000000 #define BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM 0x80000001 +#define BNXT_MGMT_OPCODE_DCB_OPS 0x80000002 #define BNXT_MGMT_MAX_HWRM_REQ_LENGTH HWRM_MAX_REQ_LEN #define BNXT_MGMT_MAX_HWRM_RESP_LENGTH (512) @@ -118,9 +119,31 @@ struct bnxt_mgmt_req_hdr { }; struct bnxt_mgmt_req { - struct bnxt_mgmt_req_hdr hdr; - union { - uint64_t hreq; - } req; + struct bnxt_mgmt_req_hdr hdr; + union { + uint64_t hreq; + } req; }; +struct bnxt_mgmt_app_tlv { + uint32_t num_app; + struct bnxt_dcb_app app[128]; +} __attribute__ ((__packed__)); + +struct bnxt_mgmt_dcb { + struct bnxt_mgmt_req_hdr hdr; +#define BNXT_MGMT_DCB_GET_ETS 0x1 +#define BNXT_MGMT_DCB_SET_ETS 0x2 +#define BNXT_MGMT_DCB_GET_PFC 0x3 +#define BNXT_MGMT_DCB_SET_PFC 0x4 +#define BNXT_MGMT_DCB_SET_APP 0x5 +#define BNXT_MGMT_DCB_DEL_APP 0x6 +#define BNXT_MGMT_DCB_LIST_APP 0x7 +#define BNXT_MGMT_DCB_MAX BNXT_MGMT_DCB_LIST_APP + uint32_t op; + union { + struct bnxt_ieee_ets ets; + struct bnxt_ieee_pfc pfc; + struct bnxt_mgmt_app_tlv app_tlv; + } req; +} __attribute__ ((__packed__)); diff --git a/sys/dev/bnxt/bnxt_sysctl.c b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c index 09e79a72f68f..51438e657546 100644 --- a/sys/dev/bnxt/bnxt_sysctl.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c @@ -29,11 +29,17 @@ #include <sys/types.h> #include <sys/sysctl.h> #include <sys/ctype.h> +#include <linux/delay.h> #include "bnxt.h" #include "bnxt_hwrm.h" #include "bnxt_sysctl.h" +DEFINE_MUTEX(tmp_mutex); /* mutex lock for driver */ +extern void bnxt_fw_reset(struct bnxt_softc *bp); +extern void bnxt_queue_sp_work(struct bnxt_softc *bp); +extern void +process_nq(struct bnxt_softc *softc, uint16_t nqid); /* * We want to create: * dev.bnxt.0.hwstats.txq0 @@ -105,6 +111,16 @@ bnxt_init_sysctl_ctx(struct bnxt_softc *softc) return ENOMEM; } + sysctl_ctx_init(&softc->dcb_ctx); + ctx = device_get_sysctl_ctx(softc->dev); + softc->dcb_oid = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, + "dcb", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Data Center Bridging"); + if (!softc->dcb_oid) { + sysctl_ctx_free(&softc->dcb_ctx); + return ENOMEM; + } + return 0; } @@ -151,6 +167,14 @@ bnxt_free_sysctl_ctx(struct bnxt_softc *softc) softc->flow_ctrl_oid = NULL; } + if (softc->dcb_oid != NULL) { + orc = sysctl_ctx_free(&softc->dcb_ctx); + if (orc) + rc = orc; + else + softc->dcb_oid = NULL; + } + return rc; } @@ -529,7 +553,7 @@ bnxt_create_port_stats_sysctls(struct bnxt_softc *softc) "rx_stat_err", CTLFLAG_RD, &softc->rx_port_stats->rx_stat_err, "Received stat err"); - if (BNXT_CHIP_P5(softc) && + if (BNXT_CHIP_P5_PLUS(softc) && (softc->flags & BNXT_FLAG_FW_CAP_EXT_STATS)) { SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, "tx_bytes_cos0", CTLFLAG_RD, @@ -581,6 +605,55 @@ bnxt_create_port_stats_sysctls(struct bnxt_softc *softc) &softc->tx_port_stats_ext->tx_packets_cos7, "Transmitted packets count cos7"); SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri0", CTLFLAG_RD, + &softc->tx_bytes_pri[0], "Transmitted bytes count pri0"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri0", CTLFLAG_RD, + &softc->tx_packets_pri[0], "Transmitted packets count pri0"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri1", CTLFLAG_RD, + &softc->tx_bytes_pri[1], "Transmitted bytes count pri1"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri1", CTLFLAG_RD, + &softc->tx_packets_pri[1], "Transmitted packets count pri1"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri2", CTLFLAG_RD, + &softc->tx_bytes_pri[2], "Transmitted bytes count pri2"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri2", CTLFLAG_RD, + &softc->tx_packets_pri[2], "Transmitted packets count pri2"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri3", CTLFLAG_RD, + &softc->tx_bytes_pri[3], "Transmitted bytes count pri3"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri3", CTLFLAG_RD, + &softc->tx_packets_pri[3], "Transmitted packets count pri3"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri4", CTLFLAG_RD, + &softc->tx_bytes_pri[4], "Transmitted bytes count pri4"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri4", CTLFLAG_RD, + &softc->tx_packets_pri[4], "Transmitted packets count pri4"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri5", CTLFLAG_RD, + &softc->tx_bytes_pri[5], "Transmitted bytes count pri5"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri5", CTLFLAG_RD, + &softc->tx_packets_pri[5], "Transmitted packets count pri5"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri6", CTLFLAG_RD, + &softc->tx_bytes_pri[6], "Transmitted bytes count pri6"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri6", CTLFLAG_RD, + &softc->tx_packets_pri[6], "Transmitted packets count pri6"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_bytes_pri7", CTLFLAG_RD, + &softc->tx_bytes_pri[7], "Transmitted bytes count pri7"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tx_packets_pri7", CTLFLAG_RD, + &softc->tx_packets_pri[7], "Transmitted packets count pri7"); + + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, "pfc_pri0_tx_duration_us", CTLFLAG_RD, &softc->tx_port_stats_ext->pfc_pri0_tx_duration_us, "Time duration between" "XON to XOFF and XOFF to XON for pri0"); @@ -714,6 +787,55 @@ bnxt_create_port_stats_sysctls(struct bnxt_softc *softc) &softc->rx_port_stats_ext->rx_packets_cos7, "Received packets count cos7"); SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri0", CTLFLAG_RD, + &softc->rx_bytes_pri[0], "Received bytes count pri0"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri0", CTLFLAG_RD, + &softc->rx_packets_pri[0], "Received packets count pri0"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri1", CTLFLAG_RD, + &softc->rx_bytes_pri[1], "Received bytes count pri1"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri1", CTLFLAG_RD, + &softc->rx_packets_pri[1], "Received packets count pri1"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri2", CTLFLAG_RD, + &softc->rx_bytes_pri[2], "Received bytes count pri2"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri2", CTLFLAG_RD, + &softc->rx_packets_pri[2], "Received packets count pri2"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri3", CTLFLAG_RD, + &softc->rx_bytes_pri[3], "Received bytes count pri3"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri3", CTLFLAG_RD, + &softc->rx_packets_pri[3], "Received packets count pri3"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri4", CTLFLAG_RD, + &softc->rx_bytes_pri[4], "Received bytes count pri4"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri4", CTLFLAG_RD, + &softc->rx_packets_pri[4], "Received packets count pri4"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri5", CTLFLAG_RD, + &softc->rx_bytes_pri[5], "Received bytes count pri5"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri5", CTLFLAG_RD, + &softc->rx_packets_pri[5], "Received packets count pri5"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri6", CTLFLAG_RD, + &softc->rx_bytes_pri[6], "Received bytes count pri6"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri6", CTLFLAG_RD, + &softc->rx_packets_pri[6], "Received packets count pri6"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_bytes_pri7", CTLFLAG_RD, + &softc->rx_bytes_pri[7], "Received bytes count pri7"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "rx_packets_pri7", CTLFLAG_RD, + &softc->rx_packets_pri[7], "Received packets count pri7"); + + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, "pfc_pri0_rx_duration_us", CTLFLAG_RD, &softc->rx_port_stats_ext->pfc_pri0_rx_duration_us, "Time duration in receiving" "between XON to XOFF and XOFF to XON for pri0"); @@ -880,7 +1002,7 @@ bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr) if (!oid) return ENOMEM; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, "nq_num_ints", CTLFLAG_RD, &softc->nq_rings[rxr].int_count, "Num Interrupts"); @@ -1052,9 +1174,6 @@ bnxt_create_ver_sysctls(struct bnxt_softc *softc) "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0, "HWRM firmware version"); SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, - "hwrm_fw", CTLFLAG_RD, vi->hwrm_fw_ver, 0, - "HWRM firmware version"); - SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0, "management firmware version"); SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, @@ -1436,6 +1555,46 @@ bnxt_set_coal_tx_frames_irq(SYSCTL_HANDLER_ARGS) { return rc; } +static +void simulate_reset(struct bnxt_softc *bp, char *fwcli_string) +{ + struct hwrm_dbg_fw_cli_input req = {0}; + int rc = 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_DBG_FW_CLI); + req.cmpl_ring = -1; + req.target_id = -1; + req.cli_cmd_len = strlen(fwcli_string); + req.host_buf_len = 64 * 1024; + strcpy((char *)req.cli_cmd, fwcli_string); + + BNXT_HWRM_LOCK(bp); + rc = _hwrm_send_message(bp, &req, sizeof(req)); + if (rc) { + device_printf(bp->dev, " Manual FW fault failed, rc:%x\n", rc); + } + BNXT_HWRM_UNLOCK(bp); +} + +static int +bnxt_reset_ctrl(SYSCTL_HANDLER_ARGS) { + struct bnxt_softc *softc = arg1; + int rc = 0; + char buf[50] = {0}; + + if (softc == NULL) + return EBUSY; + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + if (BNXT_CHIP_P5_PLUS(softc)) + simulate_reset(softc, buf); + + return rc; +} + int bnxt_create_config_sysctls_pre(struct bnxt_softc *softc) { @@ -1460,35 +1619,43 @@ bnxt_create_config_sysctls_pre(struct bnxt_softc *softc) SYSCTL_ADD_CONST_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD, if_name(iflib_get_ifp(softc->ctx)), "interface name"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_rx_usecs, "I", "interrupt coalescing Rx Usecs"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_rx_frames, "I", "interrupt coalescing Rx Frames"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs_irq", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs_irq", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_rx_usecs_irq, "I", "interrupt coalescing Rx Usecs IRQ"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames_irq", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames_irq", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_rx_frames_irq, "I", "interrupt coalescing Rx Frames IRQ"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_tx_usecs, "I", "interrupt coalescing Tx Usces"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, - bnxt_set_coal_tx_frames, "I", "interrupt coalescing Tx Frames"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs_irq", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + bnxt_set_coal_tx_frames, "I", "interrupt coalescing Tx Frames"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs_irq", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_tx_usecs_irq, "I", - "interrupt coalescing Tx Usecs IRQ"); - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames_irq", - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, + "interrupt coalescing Tx Usecs IRQ"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames_irq", + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0, bnxt_set_coal_tx_frames_irq, "I", "interrupt coalescing Tx Frames IRQ"); - + SYSCTL_ADD_U32(ctx, children, OID_AUTO, "flags", CTLFLAG_RD, + &softc->flags, 0, "flags"); + SYSCTL_ADD_U64(ctx, children, OID_AUTO, "fw_cap", CTLFLAG_RD, + &softc->fw_cap, 0, "FW caps"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, + "reset_ctrl", CTLTYPE_STRING | CTLFLAG_RWTUN, softc, + 0, bnxt_reset_ctrl, "A", + "Issue controller reset: 0 / 1"); return 0; } @@ -1618,6 +1785,349 @@ bnxt_create_hw_lro_sysctls(struct bnxt_softc *softc) return 0; } +static int +bnxt_dcb_dcbx_cap(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + int val; + int rc; + + val = bnxt_dcb_getdcbx(softc); + rc = sysctl_handle_int(oidp, &val, 0, req); + if (rc || !req->newptr) + return rc; + + bnxt_dcb_setdcbx(softc, val); + + return rc; +} + +static char +bnxt_ets_tsa_to_str(struct bnxt_softc *softc, uint32_t tc) +{ + switch (softc->ieee_ets->tc_tsa[tc]) { + case BNXT_IEEE_8021QAZ_TSA_STRICT: + return 's'; + case BNXT_IEEE_8021QAZ_TSA_ETS: + return 'e'; + default: + return 'X'; + + } +} + +static uint32_t +bnxt_ets_str_to_tsa(char tsa_str) +{ + switch (tsa_str) { + case 's': + return BNXT_IEEE_8021QAZ_TSA_STRICT; + case 'e': + return BNXT_IEEE_8021QAZ_TSA_ETS; + default: + return -1; + } +} + +static int +bnxt_ets_get_val(struct bnxt_softc *softc, uint32_t type, uint32_t tc) +{ + switch (type) { + case BNXT_TYPE_ETS_TSA: + if (softc->ieee_ets) + return softc->ieee_ets->tc_tsa[tc]; + break; + case BNXT_TYPE_ETS_PRI2TC: + if (softc->ieee_ets) + return softc->ieee_ets->prio_tc[tc]; + break; + case BNXT_TYPE_ETS_TCBW: + if (softc->ieee_ets) + return softc->ieee_ets->tc_tx_bw[tc]; + break; + default: + break; + } + + return -1; +} + +static void +bnxt_pfc_get_string(struct bnxt_softc *softc, char *buf, struct bnxt_ieee_pfc *pfc) +{ + uint32_t i; + bool found = false; + + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { + if (pfc->pfc_en & (1 << i)) { + if (found) + buf += sprintf(buf, ", "); + buf += sprintf(buf, "%d", i); + found = true; + } + } + + if (!found) + buf += sprintf(buf, "none"); +} + +static const char *bnxt_get_tlv_selector_str(uint8_t selector) +{ + switch (selector) { + case BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE: + return "Ethertype"; + case BNXT_IEEE_8021QAZ_APP_SEL_DGRAM: + return "UDP or DCCP"; + case BNXT_IEEE_8021QAZ_APP_SEL_DSCP: + return "DSCP"; + default: + return "Unknown"; + } +} + +static void +bnxt_app_tlv_get_string(struct sbuf *sb, struct bnxt_dcb_app *app, int num) +{ + int i; + + if (num == 0) { + sbuf_printf(sb, " None"); + return; + } + + sbuf_putc(sb, '\n'); + for (i = 0; i < num; i++) { + sbuf_printf(sb, "\tAPP#%0d:\tpri: %d,\tSel: %d,\t%s: %d\n", + i, + app[i].priority, + app[i].selector, + bnxt_get_tlv_selector_str(app[i].selector), + app[i].protocol); + } +} + +static void +bnxt_ets_get_string(struct bnxt_softc *softc, char *buf) +{ + uint32_t type, i; + + type = BNXT_TYPE_ETS_TSA; + for (type = 0; type < BNXT_TYPE_ETS_MAX; type++) { + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { + if (i == 0) + buf += sprintf(buf, "%s:", BNXT_ETS_TYPE_STR[type]); + + if (!softc->ieee_ets) + buf += sprintf(buf, "x"); + else if (type == BNXT_TYPE_ETS_TSA) + buf += sprintf(buf, "%c", bnxt_ets_tsa_to_str(softc, i)); + else + buf += sprintf(buf, "%d", bnxt_ets_get_val(softc, type, i)); + + if (i != BNXT_IEEE_8021QAZ_MAX_TCS - 1) + buf += sprintf(buf, ","); + } + if (type != BNXT_TYPE_ETS_MAX - 1) + buf += sprintf(buf, "#"); + } +} + +static int +bnxt_dcb_list_app(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + struct bnxt_dcb_app app[128] = {0}; + struct bnxt_softc *softc = arg1; + int rc, num_inputs = 0; + + sbuf_new_for_sysctl(&sb, NULL, 128, req); + bnxt_dcb_ieee_listapp(softc, app, nitems(app), &num_inputs); + bnxt_app_tlv_get_string(&sb, app, num_inputs); + rc = sbuf_finish(&sb); + sbuf_delete(&sb); + return rc; +} + +static int +bnxt_dcb_del_app(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + struct bnxt_dcb_app app = {0}; + char buf[256] = {0}; + int rc, num_inputs; + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + num_inputs = sscanf(buf, "%hhu,%hhu,%hd", &app.priority, &app.selector, &app.protocol); + + if (num_inputs != 3) { + device_printf(softc->dev, + "Invalid app tlv syntax, inputs = %d\n", num_inputs); + return EINVAL; + } + + bnxt_dcb_ieee_delapp(softc, &app); + + return rc; +} +static int +bnxt_dcb_set_app(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + struct bnxt_dcb_app app = {0}; + char buf[256] = {0}; + int rc, num_inputs; + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + num_inputs = sscanf(buf, "%hhu,%hhu,%hd", &app.priority, &app.selector, &app.protocol); + + if (num_inputs != 3) { + device_printf(softc->dev, + "Invalid app tlv syntax, inputs = %d\n", num_inputs); + return EINVAL; + } + + bnxt_dcb_ieee_setapp(softc, &app); + + return rc; +} + +static int +bnxt_dcb_pfc(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + struct bnxt_ieee_pfc pfc = {0}; + int rc, i, num_inputs; + char buf[256] = {0}; + int pri_mask = 0; + char pri[8]; + + rc = bnxt_dcb_ieee_getpfc(softc, &pfc); + if (!rc) + bnxt_pfc_get_string(softc, buf, &pfc); + else + sprintf(buf, "## getpfc failed with error %d ##", rc); + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + /* Check for 'none' string first */ + if (sscanf(buf, "%s", buf) == 1) { + if (strncmp(buf, "none", 8) == 0) { + goto configure; + } + } + num_inputs = sscanf(buf, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", + &pri[0], &pri[1], &pri[2], &pri[3], &pri[4], + &pri[5], &pri[6], &pri[7]); + + if (num_inputs < 1 || num_inputs > 8) { + device_printf(softc->dev, + "Invalid pfc syntax, inputs = %d\n", num_inputs); + return EINVAL; + } + + for (i = 0; i < num_inputs; i++) { + if (pri[i] > 7 || pri[i] < 0) { + device_printf(softc->dev, + "Invalid priority %d. Valid priorties are " + "from 0 to 7 and string \"none\".\n", pri[i]); + return EINVAL; + } + + pri_mask |= (1 << pri[i]) & 0xFF; + } + +configure: + pfc.pfc_en = pri_mask; + rc = bnxt_dcb_ieee_setpfc(softc, &pfc); + if (rc) + device_printf(softc->dev, + "setpfc failed with status %d\n", rc); + return rc; +} + +static int +bnxt_dcb_ets(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + struct bnxt_ieee_ets ets = {0}; + int rc = 0, i, num_inputs; + char buf[256] = {0}; + char tsa[8]; + + rc = bnxt_dcb_ieee_getets(softc, &ets); + if (!rc) + bnxt_ets_get_string(softc, buf); + else + sprintf(buf, "## getets failed with error %d ##", rc); + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + num_inputs = sscanf(buf, "tsa:%c,%c,%c,%c,%c,%c,%c,%c#" + "pri2tc:%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu#" + "tcbw:%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", + &tsa[0], &tsa[1], &tsa[2], &tsa[3], &tsa[4], &tsa[5], &tsa[6], &tsa[7], + &ets.prio_tc[0], &ets.prio_tc[1], &ets.prio_tc[2], &ets.prio_tc[3], + &ets.prio_tc[4], &ets.prio_tc[5], &ets.prio_tc[6], &ets.prio_tc[7], + &ets.tc_tx_bw[0], &ets.tc_tx_bw[1], &ets.tc_tx_bw[2], &ets.tc_tx_bw[3], + &ets.tc_tx_bw[4], &ets.tc_tx_bw[5], &ets.tc_tx_bw[6], &ets.tc_tx_bw[7]); + + if (num_inputs != 24) + return EINVAL; + + for ( i= 0; i < 8; i++) + ets.tc_tsa[i] = bnxt_ets_str_to_tsa(tsa[i]); + + rc = bnxt_dcb_ieee_setets(softc, &ets); + + return rc; +} + +int +bnxt_create_dcb_sysctls(struct bnxt_softc *softc) +{ + struct sysctl_oid *oid = softc->dcb_oid; + + if (!oid) + return ENOMEM; + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "dcbx_cap", CTLTYPE_INT | CTLFLAG_RWTUN, softc, + 0, bnxt_dcb_dcbx_cap, "A", + "Enable DCB Capability Exchange Protocol (DCBX) capabilities"); + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "ets", + CTLTYPE_STRING | CTLFLAG_RWTUN, softc, 0, + bnxt_dcb_ets, "A", "Enhanced Transmission Selection (ETS)"); + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "pfc", + CTLTYPE_STRING | CTLFLAG_RWTUN, softc, 0, + bnxt_dcb_pfc, "A", "Enhanced Transmission Selection (ETS)"); + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "set_apptlv", + CTLTYPE_STRING | CTLFLAG_WR, softc, 0, + bnxt_dcb_set_app, "A", "Set App TLV"); + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "del_apptlv", + CTLTYPE_STRING | CTLFLAG_WR, softc, 0, + bnxt_dcb_del_app, "A", "Delete App TLV"); + + SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "list_apptlv", + CTLTYPE_STRING | CTLFLAG_RD, softc, 0, + bnxt_dcb_list_app, "A", "List all App TLVs"); + + return 0; +} + int bnxt_create_config_sysctls_post(struct bnxt_softc *softc) { diff --git a/sys/dev/bnxt/bnxt_sysctl.h b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.h index a2ca3a8a559f..d4c9e908b9c1 100644 --- a/sys/dev/bnxt/bnxt_sysctl.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.h @@ -40,3 +40,5 @@ int bnxt_create_config_sysctls_pre(struct bnxt_softc *softc); int bnxt_create_config_sysctls_post(struct bnxt_softc *softc); int bnxt_create_hw_lro_sysctls(struct bnxt_softc *softc); int bnxt_create_pause_fc_sysctls(struct bnxt_softc *softc); +int bnxt_create_dcb_sysctls(struct bnxt_softc *softc); +int bnxt_create_dcb_ets_sysctls(struct bnxt_softc *softc); diff --git a/sys/dev/bnxt/bnxt_txrx.c b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c index 98575234c515..2e10de6f0174 100644 --- a/sys/dev/bnxt/bnxt_txrx.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c @@ -97,6 +97,7 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) uint16_t lflags; uint32_t cfa_meta; int seg = 0; + uint8_t wrap = 0; /* If we have offloads enabled, we need to use two BDs. */ if ((pi->ipi_csum_flags & (CSUM_OFFLOAD | CSUM_TSO | CSUM_IP)) || @@ -123,7 +124,18 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) if (need_hi) { flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG; + /* Handle wrapping */ + if (pi->ipi_new_pidx == txr->ring_size - 1) + wrap = 1; + pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + + /* Toggle epoch bit on wrap */ + if (wrap && pi->ipi_new_pidx == 0) + txr->epoch_bit = !txr->epoch_bit; + if (pi->ipi_new_pidx < EPOCH_ARR_SZ) + txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit; + tbdh = &((struct tx_bd_long_hi *)txr->vaddr)[pi->ipi_new_pidx]; tbdh->kid_or_ts_high_mss = htole16(pi->ipi_tso_segsz); tbdh->kid_or_ts_low_hdr_size = htole16((pi->ipi_ehdrlen + pi->ipi_ip_hlen + @@ -157,7 +169,15 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) for (; seg < pi->ipi_nsegs; seg++) { tbd->flags_type = htole16(flags_type); + + if (pi->ipi_new_pidx == txr->ring_size - 1) + wrap = 1; pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + if (wrap && pi->ipi_new_pidx == 0) + txr->epoch_bit = !txr->epoch_bit; + if (pi->ipi_new_pidx < EPOCH_ARR_SZ) + txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit; + tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx]; tbd->len = htole16(pi->ipi_segs[seg].ds_len); tbd->addr = htole64(pi->ipi_segs[seg].ds_addr); @@ -165,7 +185,13 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) } flags_type |= TX_BD_SHORT_FLAGS_PACKET_END; tbd->flags_type = htole16(flags_type); + if (pi->ipi_new_pidx == txr->ring_size - 1) + wrap = 1; pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + if (wrap && pi->ipi_new_pidx == 0) + txr->epoch_bit = !txr->epoch_bit; + if (pi->ipi_new_pidx < EPOCH_ARR_SZ) + txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit; return 0; } @@ -189,16 +215,21 @@ bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, bool clear) struct tx_cmpl *cmpl = (struct tx_cmpl *)cpr->ring.vaddr; int avail = 0; uint32_t cons = cpr->cons; + uint32_t raw_cons = cpr->raw_cons; bool v_bit = cpr->v_bit; bool last_v_bit; uint32_t last_cons; + uint32_t last_raw_cons; uint16_t type; uint16_t err; for (;;) { last_cons = cons; + last_raw_cons = raw_cons; last_v_bit = v_bit; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + raw_cons++; CMPL_PREFETCH_NEXT(cpr, cons); if (!CMP_VALID(&cmpl[cons], v_bit)) @@ -226,8 +257,10 @@ bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, bool clear) default: if (type & 1) { NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); - if (!CMP_VALID(&cmpl[cons], v_bit)) + raw_cons++; + if (!CMP_VALID(&cmpl[cons], v_bit)) { goto done; + } } device_printf(softc->dev, "Unhandled TX completion type %u\n", type); @@ -238,6 +271,7 @@ done: if (clear && avail) { cpr->cons = last_cons; + cpr->raw_cons = last_raw_cons; cpr->v_bit = last_v_bit; softc->db_ops.bnxt_db_tx_cq(cpr, 0); } @@ -284,9 +318,16 @@ bnxt_isc_rxd_refill(void *sc, if_rxd_update_t iru) rxbd[pidx].opaque = (((rxqid & 0xff) << 24) | (flid << 16) | (frag_idxs[i])); rxbd[pidx].addr = htole64(paddrs[i]); - if (++pidx == rx_ring->ring_size) + + /* Increment pidx and handle wrap-around */ + if (++pidx == rx_ring->ring_size) { pidx = 0; + rx_ring->epoch_bit = !rx_ring->epoch_bit; + } + if (pidx < EPOCH_ARR_SZ) + rx_ring->epoch_arr[pidx] = rx_ring->epoch_bit; } + return; } @@ -337,6 +378,7 @@ bnxt_isc_rxd_available(void *sc, uint16_t rxqid, qidx_t idx, qidx_t budget) type = le16toh(cmp[cons].type) & CMPL_BASE_TYPE_MASK; switch (type) { case CMPL_BASE_TYPE_RX_L2: + case CMPL_BASE_TYPE_RX_L2_V3: rcp = (void *)&cmp[cons]; ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >> RX_PKT_CMPL_AGG_BUFS_SFT; @@ -470,6 +512,7 @@ bnxt_pkt_get_l2(struct bnxt_softc *softc, if_rxd_info_t ri, /* Now the second 16-byte BD */ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); rcph = &((struct rx_pkt_cmpl_hi *)cpr->ring.vaddr)[cpr->cons]; @@ -501,6 +544,7 @@ bnxt_pkt_get_l2(struct bnxt_softc *softc, if_rxd_info_t ri, /* And finally the ag ring stuff. */ for (i=1; i < ri->iri_nfrags; i++) { NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons]; @@ -551,6 +595,7 @@ bnxt_pkt_get_tpa(struct bnxt_softc *softc, if_rxd_info_t ri, /* Now the second 16-byte BD */ NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); flags2 = le32toh(tpas->high.flags2); @@ -576,6 +621,7 @@ bnxt_pkt_get_tpa(struct bnxt_softc *softc, if_rxd_info_t ri, /* Now the ag ring stuff. */ for (i=1; i < ri->iri_nfrags; i++) { NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons]; @@ -612,6 +658,7 @@ bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri) for (;;) { NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); CMPL_PREFETCH_NEXT(cpr, cpr->cons); cmp = &((struct cmpl_base *)cpr->ring.vaddr)[cpr->cons]; @@ -621,10 +668,12 @@ bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri) switch (type) { case CMPL_BASE_TYPE_RX_L2: + case CMPL_BASE_TYPE_RX_L2_V3: return bnxt_pkt_get_l2(softc, ri, cpr, flags_type); case CMPL_BASE_TYPE_RX_TPA_END: return bnxt_pkt_get_tpa(softc, ri, cpr, flags_type); case CMPL_BASE_TYPE_RX_TPA_START: + case CMPL_BASE_TYPE_RX_TPA_START_V3: rtpa = (void *)&cmp_q[cpr->cons]; agg_id = (rtpa->agg_id & RX_TPA_START_CMPL_AGG_ID_MASK) >> @@ -632,6 +681,7 @@ bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri) softc->rx_rings[ri->iri_qsidx].tpa_start[agg_id].low = *rtpa; NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); CMPL_PREFETCH_NEXT(cpr, cpr->cons); @@ -645,6 +695,7 @@ bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri) if (type & 1) { NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + cpr->raw_cons++; ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); CMPL_PREFETCH_NEXT(cpr, cpr->cons); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c new file mode 100644 index 000000000000..3c1f62cb4da3 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c @@ -0,0 +1,526 @@ +/*- + * 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/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <linux/bitmap.h> +#include <linux/rcupdate.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_var.h> +#include <net/ethernet.h> +#include <net/iflib.h> + +#include "hsi_struct_def.h" +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include "bnxt_ulp.h" + +void bnxt_destroy_irq(struct bnxt_softc *softc); + +static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id, + struct bnxt_ulp_ops *ulp_ops, void *handle) +{ + struct bnxt_softc *bp = edev->softc; + struct bnxt_ulp *ulp; + int rc = 0; + + if (ulp_id >= BNXT_MAX_ULP) + return -EINVAL; + + mtx_lock(&bp->en_ops_lock); + ulp = &edev->ulp_tbl[ulp_id]; + if (rcu_access_pointer(ulp->ulp_ops)) { + device_printf(bp->dev, "ulp id %d already registered\n", ulp_id); + rc = -EBUSY; + goto exit; + } + + edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED; + atomic_set(&ulp->ref_count, 0); + ulp->handle = handle; + rcu_assign_pointer(ulp->ulp_ops, ulp_ops); + + if (ulp_id == BNXT_ROCE_ULP) { + if (test_bit(BNXT_STATE_OPEN, &bp->state) && bp->is_dev_init) + bnxt_hwrm_vnic_cfg(bp, &bp->vnic_info); + } + +exit: + mtx_unlock(&bp->en_ops_lock); + return rc; +} + +static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id) +{ + struct bnxt_softc *bp = edev->softc; + struct bnxt_ulp *ulp; + int i = 0; + + if (ulp_id >= BNXT_MAX_ULP) + return -EINVAL; + + ulp = &edev->ulp_tbl[ulp_id]; + if (!rcu_access_pointer(ulp->ulp_ops)) { + device_printf(bp->dev, "ulp id %d not registered\n", ulp_id); + return -EINVAL; + } + if (ulp_id == BNXT_ROCE_ULP && ulp->msix_requested) + edev->en_ops->bnxt_free_msix(edev, ulp_id); + + mtx_lock(&bp->en_ops_lock); + RCU_INIT_POINTER(ulp->ulp_ops, NULL); + synchronize_rcu(); + ulp->max_async_event_id = 0; + ulp->async_events_bmap = NULL; + while (atomic_read(&ulp->ref_count) != 0 && i < 10) { + msleep(100); + i++; + } + mtx_unlock(&bp->en_ops_lock); + return 0; +} + +static void bnxt_fill_msix_vecs(struct bnxt_softc *bp, struct bnxt_msix_entry *ent) +{ + struct bnxt_en_dev *edev = bp->edev; + int num_msix, idx, i; + + num_msix = edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested; + idx = edev->ulp_tbl[BNXT_ROCE_ULP].msix_base; + for (i = 0; i < num_msix; i++) { + ent[i].vector = bp->irq_tbl[idx + i].vector; + ent[i].ring_idx = idx + i; + if (BNXT_CHIP_P5_PLUS(bp)) + ent[i].db_offset = DB_PF_OFFSET_P5; + else + ent[i].db_offset = (idx + i) * 0x80; + + } +} + +static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, + struct bnxt_msix_entry *ent, int num_msix) +{ + struct bnxt_softc *bp = edev->softc; + int avail_msix, idx; + + if (ulp_id != BNXT_ROCE_ULP) + return -EINVAL; + + if (edev->ulp_tbl[ulp_id].msix_requested) + return -EAGAIN; + + idx = bp->total_irqs - BNXT_ROCE_IRQ_COUNT; + avail_msix = BNXT_ROCE_IRQ_COUNT; + + mtx_lock(&bp->en_ops_lock); + edev->ulp_tbl[ulp_id].msix_base = idx; + edev->ulp_tbl[ulp_id].msix_requested = avail_msix; + + bnxt_fill_msix_vecs(bp, ent); + edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED; + mtx_unlock(&bp->en_ops_lock); + return avail_msix; +} + +static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id) +{ + struct bnxt_softc *bp = edev->softc; + + if (ulp_id != BNXT_ROCE_ULP) + return -EINVAL; + + if (!(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED)) + return 0; + + mtx_lock(&bp->en_ops_lock); + edev->ulp_tbl[ulp_id].msix_requested = 0; + edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED; + if (edev->flags & BNXT_EN_FLAG_ULP_STOPPED) + goto stopped; + +stopped: + mtx_unlock(&bp->en_ops_lock); + + return 0; +} + +int bnxt_get_ulp_msix_num(struct bnxt_softc *bp) +{ + if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) { + struct bnxt_en_dev *edev = bp->edev; + + return edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested; + } + return 0; +} + +int bnxt_get_ulp_msix_base(struct bnxt_softc *bp) +{ + if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) { + struct bnxt_en_dev *edev = bp->edev; + + if (edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested) + return edev->ulp_tbl[BNXT_ROCE_ULP].msix_base; + } + return 0; +} + +static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id, + struct bnxt_fw_msg *fw_msg) +{ + struct bnxt_softc *softc = edev->softc; + int rc; + + if ((ulp_id != BNXT_ROCE_ULP) && softc->fw_reset_state) + return -EBUSY; + + rc = bnxt_hwrm_passthrough(softc, fw_msg->msg, fw_msg->msg_len, fw_msg->resp, + fw_msg->resp_max_len, fw_msg->timeout); + return rc; +} + +static void bnxt_ulp_get(struct bnxt_ulp *ulp) +{ + atomic_inc(&ulp->ref_count); +} + +static void bnxt_ulp_put(struct bnxt_ulp *ulp) +{ + atomic_dec(&ulp->ref_count); +} + +void bnxt_ulp_stop(struct bnxt_softc *bp) +{ + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + int i; + + if (!edev) + return; + + edev->flags |= BNXT_EN_FLAG_ULP_STOPPED; + edev->en_state = bp->state; + for (i = 0; i < BNXT_MAX_ULP; i++) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[i]; + + ops = ulp->ulp_ops; + if (!ops || !ops->ulp_stop) + continue; + ops->ulp_stop(ulp->handle); + } +} + +void bnxt_ulp_start(struct bnxt_softc *bp, int err) +{ + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + int i; + + if (!edev) + return; + + edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED; + edev->en_state = bp->state; + + if (err) + return; + + for (i = 0; i < BNXT_MAX_ULP; i++) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[i]; + + ops = ulp->ulp_ops; + if (!ops || !ops->ulp_start) + continue; + ops->ulp_start(ulp->handle); + } +} + +void bnxt_ulp_sriov_cfg(struct bnxt_softc *bp, int num_vfs) +{ + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + int i; + + if (!edev) + return; + + for (i = 0; i < BNXT_MAX_ULP; i++) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[i]; + + rcu_read_lock(); + ops = rcu_dereference(ulp->ulp_ops); + if (!ops || !ops->ulp_sriov_config) { + rcu_read_unlock(); + continue; + } + bnxt_ulp_get(ulp); + rcu_read_unlock(); + ops->ulp_sriov_config(ulp->handle, num_vfs); + bnxt_ulp_put(ulp); + } +} + +void bnxt_ulp_shutdown(struct bnxt_softc *bp) +{ + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + int i; + + if (!edev) + return; + + for (i = 0; i < BNXT_MAX_ULP; i++) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[i]; + + ops = ulp->ulp_ops; + if (!ops || !ops->ulp_shutdown) + continue; + ops->ulp_shutdown(ulp->handle); + } +} + +void bnxt_ulp_irq_stop(struct bnxt_softc *bp) +{ + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + + if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED)) + return; + + if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[BNXT_ROCE_ULP]; + + if (!ulp->msix_requested) + return; + + ops = ulp->ulp_ops; + if (!ops || !ops->ulp_irq_stop) + return; + ops->ulp_irq_stop(ulp->handle); + } +} + +void bnxt_ulp_async_events(struct bnxt_softc *bp, struct hwrm_async_event_cmpl *cmpl) +{ + u16 event_id = le16_to_cpu(cmpl->event_id); + struct bnxt_en_dev *edev = bp->edev; + struct bnxt_ulp_ops *ops; + int i; + + if (!edev) + return; + + rcu_read_lock(); + for (i = 0; i < BNXT_MAX_ULP; i++) { + struct bnxt_ulp *ulp = &edev->ulp_tbl[i]; + + ops = rcu_dereference(ulp->ulp_ops); + if (!ops || !ops->ulp_async_notifier) + continue; + if (!ulp->async_events_bmap || + event_id > ulp->max_async_event_id) + continue; + + /* Read max_async_event_id first before testing the bitmap. */ + rmb(); + if (edev->flags & BNXT_EN_FLAG_ULP_STOPPED) + continue; + + if (test_bit(event_id, ulp->async_events_bmap)) + ops->ulp_async_notifier(ulp->handle, cmpl); + } + rcu_read_unlock(); +} + +static int bnxt_register_async_events(struct bnxt_en_dev *edev, int ulp_id, + unsigned long *events_bmap, u16 max_id) +{ + struct bnxt_softc *bp = edev->softc; + struct bnxt_ulp *ulp; + + if (ulp_id >= BNXT_MAX_ULP) + return -EINVAL; + + mtx_lock(&bp->en_ops_lock); + ulp = &edev->ulp_tbl[ulp_id]; + ulp->async_events_bmap = events_bmap; + wmb(); + ulp->max_async_event_id = max_id; + bnxt_hwrm_func_drv_rgtr(bp, events_bmap, max_id + 1, true); + mtx_unlock(&bp->en_ops_lock); + return 0; +} + +void bnxt_destroy_irq(struct bnxt_softc *softc) +{ + kfree(softc->irq_tbl); +} + +static int bnxt_populate_irq(struct bnxt_softc *softc) +{ + struct resource_list *rl = NULL; + struct resource_list_entry *rle = NULL; + struct bnxt_msix_tbl *irq_tbl = NULL; + struct pci_devinfo *dinfo = NULL; + int i; + + softc->total_irqs = softc->scctx->isc_nrxqsets + BNXT_ROCE_IRQ_COUNT; + irq_tbl = kzalloc(softc->total_irqs * sizeof(*softc->irq_tbl), GFP_KERNEL); + + if (!irq_tbl) { + device_printf(softc->dev, "Failed to allocate IRQ table\n"); + return -1; + } + dinfo = device_get_ivars(softc->pdev->dev.bsddev); + rl = &dinfo->resources; + rle = resource_list_find(rl, SYS_RES_IRQ, 1); + softc->pdev->dev.irq_start = rle->start; + softc->pdev->dev.irq_end = rle->start + softc->total_irqs; + + for (i = 0; i < softc->total_irqs; i++) { + irq_tbl[i].entry = i; + irq_tbl[i].vector = softc->pdev->dev.irq_start + i; + } + + softc->irq_tbl = irq_tbl; + + return 0; +} + +static const struct bnxt_en_ops bnxt_en_ops_tbl = { + .bnxt_register_device = bnxt_register_dev, + .bnxt_unregister_device = bnxt_unregister_dev, + .bnxt_request_msix = bnxt_req_msix_vecs, + .bnxt_free_msix = bnxt_free_msix_vecs, + .bnxt_send_fw_msg = bnxt_send_msg, + .bnxt_register_fw_async_events = bnxt_register_async_events, +}; + +void bnxt_aux_dev_release(struct device *dev) +{ + struct bnxt_aux_dev *bnxt_adev = + container_of(dev, struct bnxt_aux_dev, aux_dev.dev); + struct bnxt_softc *bp = bnxt_adev->edev->softc; + + kfree(bnxt_adev->edev); + bnxt_adev->edev = NULL; + bp->edev = NULL; +} + +static inline void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt_softc *bp) +{ + edev->en_ops = &bnxt_en_ops_tbl; + edev->net = bp->ifp; + edev->pdev = bp->pdev; + edev->softc = bp; + edev->l2_db_size = bp->db_size; + mtx_init(&bp->en_ops_lock, "Ethernet ops lock", NULL, MTX_DEF); + + if (bp->flags & BNXT_FLAG_ROCEV1_CAP) + edev->flags |= BNXT_EN_FLAG_ROCEV1_CAP; + if (bp->flags & BNXT_FLAG_ROCEV2_CAP) + edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP; + if (bp->is_asym_q) + edev->flags |= BNXT_EN_FLAG_ASYM_Q; + edev->hwrm_bar = bp->hwrm_bar; + edev->port_partition_type = bp->port_partition_type; + edev->ulp_version = BNXT_ULP_VERSION; +} + +int bnxt_rdma_aux_device_del(struct bnxt_softc *softc) +{ + struct bnxt_aux_dev *bnxt_adev = softc->aux_dev; + struct auxiliary_device *adev; + + adev = &bnxt_adev->aux_dev; + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); + bnxt_destroy_irq(softc); + + return 0; +} + +int bnxt_rdma_aux_device_add(struct bnxt_softc *bp) +{ + struct bnxt_aux_dev *bnxt_adev = bp->aux_dev; + struct bnxt_en_dev *edev = bnxt_adev->edev; + struct auxiliary_device *aux_dev; + int ret = -1; + + if (bnxt_populate_irq(bp)) + return ret; + + device_printf(bp->dev, "V:D:SV:SD %x:%x:%x:%x, irq 0x%x, " + "devfn 0x%x, cla 0x%x, rev 0x%x, msi_en 0x%x\n", + bp->pdev->vendor, bp->pdev->device, bp->pdev->subsystem_vendor, + bp->pdev->subsystem_device, bp->pdev->irq, bp->pdev->devfn, + bp->pdev->class, bp->pdev->revision, bp->pdev->msi_enabled); + + aux_dev = &bnxt_adev->aux_dev; + aux_dev->id = bnxt_adev->id; + aux_dev->name = "rdma"; + aux_dev->dev.parent = &bp->pdev->dev; + aux_dev->dev.release = bnxt_aux_dev_release; + + if (!edev) { + edev = kzalloc(sizeof(*edev), GFP_KERNEL); + if (!edev) + return -ENOMEM; + } + + bnxt_set_edev_info(edev, bp); + bnxt_adev->edev = edev; + bp->edev = edev; + + ret = auxiliary_device_init(aux_dev); + if (ret) + goto err_free_edev; + + ret = auxiliary_device_add(aux_dev); + if (ret) + goto err_dev_uninit; + + return 0; +err_dev_uninit: + auxiliary_device_uninit(aux_dev); +err_free_edev: + kfree(edev); + bnxt_adev->edev = NULL; + bp->edev = NULL; + return ret; +} diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h new file mode 100644 index 000000000000..0108293046d7 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h @@ -0,0 +1,161 @@ +/*- + * 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_ULP_H +#define BNXT_ULP_H + +#include <linux/rcupdate.h> +#include "bnxt.h" + +#define BNXT_ROCE_ULP 0 +#define BNXT_OTHER_ULP 1 +#define BNXT_MAX_ULP 2 + +#define BNXT_MIN_ROCE_CP_RINGS 2 +#define BNXT_MIN_ROCE_STAT_CTXS 1 + +struct hwrm_async_event_cmpl; +struct bnxt_softc; +struct bnxt_bar_info; + +struct bnxt_msix_entry { + uint32_t vector; + uint32_t ring_idx; + uint32_t db_offset; +}; + +struct bnxt_ulp_ops { + void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *); + void (*ulp_stop)(void *); + void (*ulp_start)(void *); + void (*ulp_sriov_config)(void *, int); + void (*ulp_shutdown)(void *); + void (*ulp_irq_stop)(void *); + void (*ulp_irq_restart)(void *, struct bnxt_msix_entry *); +}; + +struct bnxt_fw_msg { + void *msg; + int msg_len; + void *resp; + int resp_max_len; + int timeout; +}; + +struct bnxt_ulp { + void *handle; + struct bnxt_ulp_ops __rcu *ulp_ops; + unsigned long *async_events_bmap; + u16 max_async_event_id; + u16 msix_requested; + u16 msix_base; + atomic_t ref_count; +}; + +struct bnxt_en_dev { + struct ifnet *net; + struct pci_dev *pdev; + struct bnxt_softc *softc; + u32 flags; + #define BNXT_EN_FLAG_ROCEV1_CAP 0x1 + #define BNXT_EN_FLAG_ROCEV2_CAP 0x2 + #define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \ + BNXT_EN_FLAG_ROCEV2_CAP) + #define BNXT_EN_FLAG_MSIX_REQUESTED 0x4 + #define BNXT_EN_FLAG_ULP_STOPPED 0x8 + #define BNXT_EN_FLAG_ASYM_Q 0x10 + #define BNXT_EN_FLAG_MULTI_HOST 0x20 +#define BNXT_EN_ASYM_Q(edev) ((edev)->flags & BNXT_EN_FLAG_ASYM_Q) +#define BNXT_EN_MH(edev) ((edev)->flags & BNXT_EN_FLAG_MULTI_HOST) + const struct bnxt_en_ops *en_ops; + struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP]; + int l2_db_size; /* Doorbell BAR size in + * bytes mapped by L2 + * driver. + */ + int l2_db_size_nc; /* Doorbell BAR size in + * bytes mapped as non- + * cacheable. + */ + u32 ulp_version; /* bnxt_re checks the + * ulp_version is correct + * to ensure compatibility + * with bnxt_en. + */ + #define BNXT_ULP_VERSION 0x695a0008 /* Change this when any interface + * structure or API changes + * between bnxt_en and bnxt_re. + */ + unsigned long en_state; + void __iomem *bar0; + u16 hw_ring_stats_size; + u16 pf_port_id; + u8 port_partition_type; +#define BNXT_EN_NPAR(edev) ((edev)->port_partition_type) + u8 port_count; + struct bnxt_dbr *en_dbr; + struct bnxt_bar_info hwrm_bar; + u32 espeed; +}; + +struct bnxt_en_ops { + int (*bnxt_register_device)(struct bnxt_en_dev *, int, + struct bnxt_ulp_ops *, void *); + int (*bnxt_unregister_device)(struct bnxt_en_dev *, int); + int (*bnxt_request_msix)(struct bnxt_en_dev *, int, + struct bnxt_msix_entry *, int); + int (*bnxt_free_msix)(struct bnxt_en_dev *, int); + int (*bnxt_send_fw_msg)(struct bnxt_en_dev *, int, + struct bnxt_fw_msg *); + int (*bnxt_register_fw_async_events)(struct bnxt_en_dev *, int, + unsigned long *, u16); + int (*bnxt_dbr_complete)(struct bnxt_en_dev *, int, u32); +}; + +static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id) +{ + if (edev && rcu_access_pointer(edev->ulp_tbl[ulp_id].ulp_ops)) + return true; + return false; +} + +int bnxt_get_ulp_msix_num(struct bnxt_softc *bp); +int bnxt_get_ulp_msix_base(struct bnxt_softc *bp); +int bnxt_get_ulp_stat_ctxs(struct bnxt_softc *bp); +void bnxt_ulp_stop(struct bnxt_softc *bp); +void bnxt_ulp_start(struct bnxt_softc *bp, int err); +void bnxt_ulp_sriov_cfg(struct bnxt_softc *bp, int num_vfs); +void bnxt_ulp_shutdown(struct bnxt_softc *bp); +void bnxt_ulp_irq_stop(struct bnxt_softc *bp); +void bnxt_ulp_irq_restart(struct bnxt_softc *bp, int err); +void bnxt_ulp_async_events(struct bnxt_softc *bp, struct hwrm_async_event_cmpl *cmpl); +struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev); +void bnxt_aux_dev_release(struct device *dev); +int bnxt_rdma_aux_device_add(struct bnxt_softc *bp); +int bnxt_rdma_aux_device_del(struct bnxt_softc *bp); +#endif diff --git a/sys/dev/bnxt/convert_hsi.pl b/sys/dev/bnxt/bnxt_en/convert_hsi.pl index 19f5d2d3aea1..19f5d2d3aea1 100755 --- a/sys/dev/bnxt/convert_hsi.pl +++ b/sys/dev/bnxt/bnxt_en/convert_hsi.pl diff --git a/sys/dev/bnxt/hsi_struct_def.h b/sys/dev/bnxt/bnxt_en/hsi_struct_def.h index 12b112c42ca7..5914c70ce671 100644 --- a/sys/dev/bnxt/hsi_struct_def.h +++ b/sys/dev/bnxt/bnxt_en/hsi_struct_def.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright (c) 2016 Broadcom, All Rights Reserved. + * Copyright (c) 2025 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 @@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$"); /* - * Copyright(c) 2001-2023, Broadcom. All rights reserved. The + * Copyright(c) 2001-2025, Broadcom. All rights reserved. The * term Broadcom refers to Broadcom Inc. and/or its subsidiaries. * Proprietary and Confidential Information. * @@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$"); #ifndef _HSI_STRUCT_DEF_H_ #define _HSI_STRUCT_DEF_H_ +#if defined(HAVE_STDINT_H) +#include <stdint.h> +#endif + /* This is the HWRM command header. */ /* hwrm_cmd_hdr (size:128b/16B) */ @@ -111,6 +115,10 @@ typedef struct hwrm_resp_hdr { #define TLV_TYPE_QUERY_ROCE_CC_GEN1 UINT32_C(0x4) /* RoCE slow path command to modify CC Gen1 support. */ #define TLV_TYPE_MODIFY_ROCE_CC_GEN1 UINT32_C(0x5) +/* RoCE slow path command to query CC Gen2 support. */ +#define TLV_TYPE_QUERY_ROCE_CC_GEN2 UINT32_C(0x6) +/* RoCE slow path command to modify CC Gen2 support. */ +#define TLV_TYPE_MODIFY_ROCE_CC_GEN2 UINT32_C(0x7) /* Engine CKV - The Alias key EC curve and ECC public key information. */ #define TLV_TYPE_ENGINE_CKV_ALIAS_ECC_PUBLIC_KEY UINT32_C(0x8001) /* Engine CKV - Initialization vector. */ @@ -193,14 +201,14 @@ typedef struct tlv { typedef struct input { /* - * This value indicates what type of request this is. The format + * This value indicates what type of request this is. The format * for the rest of the command is determined by this field. */ uint16_t req_type; /* * This value indicates the what completion ring the request will - * be optionally completed on. If the value is -1, then no - * CR completion will be generated. Any other value must be a + * be optionally completed on. If the value is -1, then no + * CR completion will be generated. Any other value must be a * valid CR ring_id value for this function. */ uint16_t cmpl_ring; @@ -216,7 +224,7 @@ typedef struct input { uint16_t target_id; /* * This is the host address where the response will be written - * when the request is complete. This area must be 16B aligned + * when the request is complete. This area must be 16B aligned * and must be cleared to zero before the request is made. */ uint64_t resp_addr; @@ -238,7 +246,7 @@ typedef struct output { /* This field provides original sequence number of the command. */ uint16_t seq_id; /* - * This field is the length of the response in bytes. The + * This field is the length of the response in bytes. The * last byte of the response is a valid flag that will read * as '1' when the command has been completely written to * memory. @@ -374,6 +382,14 @@ typedef struct hwrm_short_input { ((x) == 0x85 ? "HWRM_QUEUE_VLANPRI2PRI_CFG": \ ((x) == 0x86 ? "HWRM_QUEUE_GLOBAL_CFG": \ ((x) == 0x87 ? "HWRM_QUEUE_GLOBAL_QCFG": \ + ((x) == 0x88 ? "HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG": \ + ((x) == 0x89 ? "HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG": \ + ((x) == 0x8a ? "HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG": \ + ((x) == 0x8b ? "HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG": \ + ((x) == 0x8c ? "HWRM_QUEUE_QCAPS": \ + ((x) == 0x8d ? "HWRM_QUEUE_ADPTV_QOS_RX_TUNING_QCFG": \ + ((x) == 0x8e ? "HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG": \ + ((x) == 0x8f ? "HWRM_QUEUE_ADPTV_QOS_TX_TUNING_QCFG": \ ((x) == 0x90 ? "HWRM_CFA_L2_FILTER_ALLOC": \ ((x) == 0x91 ? "HWRM_CFA_L2_FILTER_FREE": \ ((x) == 0x92 ? "HWRM_CFA_L2_FILTER_CFG": \ @@ -392,6 +408,7 @@ typedef struct hwrm_short_input { ((x) == 0xa0 ? "HWRM_TUNNEL_DST_PORT_QUERY": \ ((x) == 0xa1 ? "HWRM_TUNNEL_DST_PORT_ALLOC": \ ((x) == 0xa2 ? "HWRM_TUNNEL_DST_PORT_FREE": \ + ((x) == 0xa3 ? "HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG": \ ((x) == 0xaf ? "HWRM_STAT_CTX_ENG_QUERY": \ ((x) == 0xb0 ? "HWRM_STAT_CTX_ALLOC": \ ((x) == 0xb1 ? "HWRM_STAT_CTX_FREE": \ @@ -439,6 +456,7 @@ typedef struct hwrm_short_input { ((x) == 0xdb ? "HWRM_PORT_EP_TX_CFG": \ ((x) == 0xdc ? "HWRM_PORT_CFG": \ ((x) == 0xdd ? "HWRM_PORT_QCFG": \ + ((x) == 0xdf ? "HWRM_PORT_MAC_QCAPS": \ ((x) == 0xe0 ? "HWRM_TEMP_MONITOR_QUERY": \ ((x) == 0xe1 ? "HWRM_REG_POWER_QUERY": \ ((x) == 0xe2 ? "HWRM_CORE_FREQUENCY_QUERY": \ @@ -456,7 +474,7 @@ typedef struct hwrm_short_input { ((x) == 0xfa ? "HWRM_CFA_METER_INSTANCE_CFG": \ ((x) == 0xfd ? "HWRM_CFA_VFR_ALLOC": \ ((x) == 0xfe ? "HWRM_CFA_VFR_FREE": \ - "Unknown decode" )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) : \ + "Unknown decode" )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) : \ (((x) < 0x180) ? \ ((x) == 0x100 ? "HWRM_CFA_VF_PAIR_ALLOC": \ ((x) == 0x101 ? "HWRM_CFA_VF_PAIR_FREE": \ @@ -500,6 +518,7 @@ typedef struct hwrm_short_input { ((x) == 0x127 ? "HWRM_CFA_LAG_GROUP_MEMBER_UNRGTR": \ ((x) == 0x128 ? "HWRM_CFA_TLS_FILTER_ALLOC": \ ((x) == 0x129 ? "HWRM_CFA_TLS_FILTER_FREE": \ + ((x) == 0x12a ? "HWRM_CFA_RELEASE_AFM_FUNC": \ ((x) == 0x12e ? "HWRM_ENGINE_CKV_STATUS": \ ((x) == 0x12f ? "HWRM_ENGINE_CKV_CKEK_ADD": \ ((x) == 0x130 ? "HWRM_ENGINE_CKV_CKEK_DELETE": \ @@ -539,7 +558,7 @@ typedef struct hwrm_short_input { ((x) == 0x163 ? "HWRM_ENGINE_NQ_FREE": \ ((x) == 0x164 ? "HWRM_ENGINE_ON_DIE_RQE_CREDITS": \ ((x) == 0x165 ? "HWRM_ENGINE_FUNC_QCFG": \ - "Unknown decode" ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) : \ + "Unknown decode" )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) : \ (((x) < 0x200) ? \ ((x) == 0x190 ? "HWRM_FUNC_RESOURCE_QCAPS": \ ((x) == 0x191 ? "HWRM_FUNC_VF_RESOURCE_CFG": \ @@ -570,7 +589,17 @@ typedef struct hwrm_short_input { ((x) == 0x1aa ? "HWRM_FUNC_DBR_RECOVERY_COMPLETED": \ ((x) == 0x1ab ? "HWRM_FUNC_SYNCE_CFG": \ ((x) == 0x1ac ? "HWRM_FUNC_SYNCE_QCFG": \ - "Unknown decode" ))))))))))))))))))))))))))))) : \ + ((x) == 0x1ad ? "HWRM_FUNC_KEY_CTX_FREE": \ + ((x) == 0x1ae ? "HWRM_FUNC_LAG_MODE_CFG": \ + ((x) == 0x1af ? "HWRM_FUNC_LAG_MODE_QCFG": \ + ((x) == 0x1b0 ? "HWRM_FUNC_LAG_CREATE": \ + ((x) == 0x1b1 ? "HWRM_FUNC_LAG_UPDATE": \ + ((x) == 0x1b2 ? "HWRM_FUNC_LAG_FREE": \ + ((x) == 0x1b3 ? "HWRM_FUNC_LAG_QCFG": \ + ((x) == 0x1c2 ? "HWRM_FUNC_TIMEDTX_PACING_RATE_ADD": \ + ((x) == 0x1c3 ? "HWRM_FUNC_TIMEDTX_PACING_RATE_DELETE": \ + ((x) == 0x1c4 ? "HWRM_FUNC_TIMEDTX_PACING_RATE_QUERY": \ + "Unknown decode" ))))))))))))))))))))))))))))))))))))))) : \ (((x) < 0x280) ? \ ((x) == 0x200 ? "HWRM_SELFTEST_QLIST": \ ((x) == 0x201 ? "HWRM_SELFTEST_EXEC": \ @@ -586,9 +615,9 @@ typedef struct hwrm_short_input { ((x) == 0x20b ? "HWRM_MFG_FRU_EEPROM_READ": \ ((x) == 0x20c ? "HWRM_MFG_SOC_IMAGE": \ ((x) == 0x20d ? "HWRM_MFG_SOC_QSTATUS": \ - ((x) == 0x20e ? "HWRM_MFG_PARAM_SEEPROM_SYNC": \ - ((x) == 0x20f ? "HWRM_MFG_PARAM_SEEPROM_READ": \ - ((x) == 0x210 ? "HWRM_MFG_PARAM_SEEPROM_HEALTH": \ + ((x) == 0x20e ? "HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE": \ + ((x) == 0x20f ? "HWRM_MFG_PARAM_CRITICAL_DATA_READ": \ + ((x) == 0x210 ? "HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH": \ ((x) == 0x211 ? "HWRM_MFG_PRVSN_EXPORT_CSR": \ ((x) == 0x212 ? "HWRM_MFG_PRVSN_IMPORT_CERT": \ ((x) == 0x213 ? "HWRM_MFG_PRVSN_GET_STATE": \ @@ -597,12 +626,27 @@ typedef struct hwrm_short_input { ((x) == 0x216 ? "HWRM_MFG_SELFTEST_QLIST": \ ((x) == 0x217 ? "HWRM_MFG_SELFTEST_EXEC": \ ((x) == 0x218 ? "HWRM_STAT_GENERIC_QSTATS": \ - "Unknown decode" ))))))))))))))))))))))))) : \ + ((x) == 0x219 ? "HWRM_MFG_PRVSN_EXPORT_CERT": \ + ((x) == 0x21a ? "HWRM_STAT_DB_ERROR_QSTATS": \ + ((x) == 0x230 ? "HWRM_PORT_POE_CFG": \ + ((x) == 0x231 ? "HWRM_PORT_POE_QCFG": \ + ((x) == 0x258 ? "HWRM_UDCC_QCAPS": \ + ((x) == 0x259 ? "HWRM_UDCC_CFG": \ + ((x) == 0x25a ? "HWRM_UDCC_QCFG": \ + ((x) == 0x25b ? "HWRM_UDCC_SESSION_CFG": \ + ((x) == 0x25c ? "HWRM_UDCC_SESSION_QCFG": \ + ((x) == 0x25d ? "HWRM_UDCC_SESSION_QUERY": \ + ((x) == 0x25e ? "HWRM_UDCC_COMP_CFG": \ + ((x) == 0x25f ? "HWRM_UDCC_COMP_QCFG": \ + ((x) == 0x260 ? "HWRM_UDCC_COMP_QUERY": \ + ((x) == 0x261 ? "HWRM_QUEUE_PFCWD_TIMEOUT_QCAPS": \ + ((x) == 0x262 ? "HWRM_QUEUE_PFCWD_TIMEOUT_CFG": \ + ((x) == 0x263 ? "HWRM_QUEUE_PFCWD_TIMEOUT_QCFG": \ + "Unknown decode" ))))))))))))))))))))))))))))))))))))))))) : \ (((x) < 0x300) ? \ ((x) == 0x2bc ? "HWRM_TF": \ ((x) == 0x2bd ? "HWRM_TF_VERSION_GET": \ ((x) == 0x2c6 ? "HWRM_TF_SESSION_OPEN": \ - ((x) == 0x2c7 ? "HWRM_TF_SESSION_ATTACH": \ ((x) == 0x2c8 ? "HWRM_TF_SESSION_REGISTER": \ ((x) == 0x2c9 ? "HWRM_TF_SESSION_UNREGISTER": \ ((x) == 0x2ca ? "HWRM_TF_SESSION_CLOSE": \ @@ -617,14 +661,6 @@ typedef struct hwrm_short_input { ((x) == 0x2da ? "HWRM_TF_TBL_TYPE_GET": \ ((x) == 0x2db ? "HWRM_TF_TBL_TYPE_SET": \ ((x) == 0x2dc ? "HWRM_TF_TBL_TYPE_BULK_GET": \ - ((x) == 0x2e2 ? "HWRM_TF_CTXT_MEM_ALLOC": \ - ((x) == 0x2e3 ? "HWRM_TF_CTXT_MEM_FREE": \ - ((x) == 0x2e4 ? "HWRM_TF_CTXT_MEM_RGTR": \ - ((x) == 0x2e5 ? "HWRM_TF_CTXT_MEM_UNRGTR": \ - ((x) == 0x2e6 ? "HWRM_TF_EXT_EM_QCAPS": \ - ((x) == 0x2e7 ? "HWRM_TF_EXT_EM_OP": \ - ((x) == 0x2e8 ? "HWRM_TF_EXT_EM_CFG": \ - ((x) == 0x2e9 ? "HWRM_TF_EXT_EM_QCFG": \ ((x) == 0x2ea ? "HWRM_TF_EM_INSERT": \ ((x) == 0x2eb ? "HWRM_TF_EM_DELETE": \ ((x) == 0x2ec ? "HWRM_TF_EM_HASH_INSERT": \ @@ -637,7 +673,13 @@ typedef struct hwrm_short_input { ((x) == 0x2fd ? "HWRM_TF_GLOBAL_CFG_GET": \ ((x) == 0x2fe ? "HWRM_TF_IF_TBL_SET": \ ((x) == 0x2ff ? "HWRM_TF_IF_TBL_GET": \ - "Unknown decode" )))))))))))))))))))))))))))))))))))))) : \ + "Unknown decode" ))))))))))))))))))))))))))))) : \ + (((x) < 0x380) ? \ + ((x) == 0x300 ? "HWRM_TF_RESC_USAGE_SET": \ + ((x) == 0x301 ? "HWRM_TF_RESC_USAGE_QUERY": \ + ((x) == 0x302 ? "HWRM_TF_TBL_TYPE_ALLOC": \ + ((x) == 0x303 ? "HWRM_TF_TBL_TYPE_FREE": \ + "Unknown decode" )))) : \ (((x) < 0x400) ? \ ((x) == 0x380 ? "HWRM_TFC_TBL_SCOPE_QCAPS": \ ((x) == 0x381 ? "HWRM_TFC_TBL_SCOPE_ID_ALLOC": \ @@ -663,11 +705,17 @@ typedef struct hwrm_short_input { ((x) == 0x395 ? "HWRM_TFC_TCAM_ALLOC": \ ((x) == 0x396 ? "HWRM_TFC_TCAM_ALLOC_SET": \ ((x) == 0x397 ? "HWRM_TFC_TCAM_FREE": \ - "Unknown decode" )))))))))))))))))))))))) : \ + ((x) == 0x398 ? "HWRM_TFC_IF_TBL_SET": \ + ((x) == 0x399 ? "HWRM_TFC_IF_TBL_GET": \ + ((x) == 0x39a ? "HWRM_TFC_TBL_SCOPE_CONFIG_GET": \ + ((x) == 0x39b ? "HWRM_TFC_RESC_USAGE_QUERY": \ + "Unknown decode" )))))))))))))))))))))))))))) : \ (((x) < 0x480) ? \ ((x) == 0x400 ? "HWRM_SV": \ "Unknown decode" ) : \ (((x) < 0xff80) ? \ + ((x) == 0xff0e ? "HWRM_DBG_SERDES_TEST": \ + ((x) == 0xff0f ? "HWRM_DBG_LOG_BUFFER_FLUSH": \ ((x) == 0xff10 ? "HWRM_DBG_READ_DIRECT": \ ((x) == 0xff11 ? "HWRM_DBG_READ_INDIRECT": \ ((x) == 0xff12 ? "HWRM_DBG_WRITE_DIRECT": \ @@ -696,8 +744,13 @@ typedef struct hwrm_short_input { ((x) == 0xff29 ? "HWRM_DBG_USEQ_RUN": \ ((x) == 0xff2a ? "HWRM_DBG_USEQ_DELIVERY_REQ": \ ((x) == 0xff2b ? "HWRM_DBG_USEQ_RESP_HDR": \ - "Unknown decode" )))))))))))))))))))))))))))) : \ - (((x) <= 0xffff) ? \ + ((x) == 0xff2c ? "HWRM_DBG_COREDUMP_CAPTURE": \ + ((x) == 0xff2d ? "HWRM_DBG_PTRACE": \ + ((x) == 0xff2e ? "HWRM_DBG_SIM_CABLE_STATE": \ + "Unknown decode" ))))))))))))))))))))))))))))))))) : \ + (((x) <= UINT16_MAX) ? \ + ((x) == 0xffea ? "HWRM_NVM_GET_VPD_FIELD_INFO": \ + ((x) == 0xffeb ? "HWRM_NVM_SET_VPD_FIELD_INFO": \ ((x) == 0xffec ? "HWRM_NVM_DEFRAG": \ ((x) == 0xffed ? "HWRM_NVM_REQ_ARBITRATION": \ ((x) == 0xffee ? "HWRM_NVM_FACTORY_DEFAULTS": \ @@ -718,8 +771,8 @@ typedef struct hwrm_short_input { ((x) == 0xfffd ? "HWRM_NVM_READ": \ ((x) == 0xfffe ? "HWRM_NVM_WRITE": \ ((x) == 0xffff ? "HWRM_NVM_RAW_WRITE_BLK": \ - "Unknown decode" )))))))))))))))))))) : \ - "Unknown decode" )))))))))) + "Unknown decode" )))))))))))))))))))))) : \ + "Unknown decode" ))))))))))) /* @@ -800,7 +853,7 @@ typedef struct cmd_nums { #define HWRM_FUNC_VLAN_QCFG UINT32_C(0x34) #define HWRM_QUEUE_PFCENABLE_QCFG UINT32_C(0x35) #define HWRM_QUEUE_PFCENABLE_CFG UINT32_C(0x36) - #define HWRM_QUEUE_PRI2COS_QCFG UINT32_C(0x37) + #define HWRM_QUEUE_PRI2COS_QCFG UINT32_C(0x37) #define HWRM_QUEUE_PRI2COS_CFG UINT32_C(0x38) #define HWRM_QUEUE_COS2BW_QCFG UINT32_C(0x39) #define HWRM_QUEUE_COS2BW_CFG UINT32_C(0x3a) @@ -848,6 +901,14 @@ typedef struct cmd_nums { #define HWRM_QUEUE_VLANPRI2PRI_CFG UINT32_C(0x85) #define HWRM_QUEUE_GLOBAL_CFG UINT32_C(0x86) #define HWRM_QUEUE_GLOBAL_QCFG UINT32_C(0x87) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG UINT32_C(0x88) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG UINT32_C(0x89) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG UINT32_C(0x8a) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG UINT32_C(0x8b) + #define HWRM_QUEUE_QCAPS UINT32_C(0x8c) + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_QCFG UINT32_C(0x8d) + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG UINT32_C(0x8e) + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_QCFG UINT32_C(0x8f) #define HWRM_CFA_L2_FILTER_ALLOC UINT32_C(0x90) #define HWRM_CFA_L2_FILTER_FREE UINT32_C(0x91) #define HWRM_CFA_L2_FILTER_CFG UINT32_C(0x92) @@ -871,6 +932,7 @@ typedef struct cmd_nums { #define HWRM_TUNNEL_DST_PORT_QUERY UINT32_C(0xa0) #define HWRM_TUNNEL_DST_PORT_ALLOC UINT32_C(0xa1) #define HWRM_TUNNEL_DST_PORT_FREE UINT32_C(0xa2) + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG UINT32_C(0xa3) #define HWRM_STAT_CTX_ENG_QUERY UINT32_C(0xaf) #define HWRM_STAT_CTX_ALLOC UINT32_C(0xb0) #define HWRM_STAT_CTX_FREE UINT32_C(0xb1) @@ -926,6 +988,8 @@ typedef struct cmd_nums { #define HWRM_PORT_EP_TX_CFG UINT32_C(0xdb) #define HWRM_PORT_CFG UINT32_C(0xdc) #define HWRM_PORT_QCFG UINT32_C(0xdd) + /* Queries MAC capabilities for the specified port */ + #define HWRM_PORT_MAC_QCAPS UINT32_C(0xdf) #define HWRM_TEMP_MONITOR_QUERY UINT32_C(0xe0) #define HWRM_REG_POWER_QUERY UINT32_C(0xe1) #define HWRM_CORE_FREQUENCY_QUERY UINT32_C(0xe2) @@ -1029,7 +1093,12 @@ typedef struct cmd_nums { #define HWRM_CFA_TLS_FILTER_ALLOC UINT32_C(0x128) /* Experimental */ #define HWRM_CFA_TLS_FILTER_FREE UINT32_C(0x129) - /* Engine CKV - Get the current allocation status of keys provisioned in the key vault. */ + /* Release an AFM function for TF control */ + #define HWRM_CFA_RELEASE_AFM_FUNC UINT32_C(0x12a) + /* + * Engine CKV - Get the current allocation status of keys provisioned in + * the key vault. + */ #define HWRM_ENGINE_CKV_STATUS UINT32_C(0x12e) /* Engine CKV - Add a new CKEK used to encrypt keys. */ #define HWRM_ENGINE_CKV_CKEK_ADD UINT32_C(0x12f) @@ -1089,7 +1158,10 @@ typedef struct cmd_nums { #define HWRM_ENGINE_STATS_CLEAR UINT32_C(0x156) /* Engine - Query the statistics accumulator for an Engine. */ #define HWRM_ENGINE_STATS_QUERY UINT32_C(0x157) - /* Engine - Query statistics counters for continuous errors from all CDDIP Engines. */ + /* + * Engine - Query statistics counters for continuous errors from all CDDIP + * Engines. + */ #define HWRM_ENGINE_STATS_QUERY_CONTINUOUS_ERROR UINT32_C(0x158) /* Engine - Allocate an Engine RQ. */ #define HWRM_ENGINE_RQ_ALLOC UINT32_C(0x15e) @@ -1171,13 +1243,39 @@ typedef struct cmd_nums { #define HWRM_FUNC_SYNCE_CFG UINT32_C(0x1ab) /* Queries SyncE configurations. */ #define HWRM_FUNC_SYNCE_QCFG UINT32_C(0x1ac) + /* The command is used to deallocate KTLS or QUIC key contexts. */ + #define HWRM_FUNC_KEY_CTX_FREE UINT32_C(0x1ad) + /* The command is used to configure link aggr group mode. */ + #define HWRM_FUNC_LAG_MODE_CFG UINT32_C(0x1ae) + /* The command is used to query link aggr group mode. */ + #define HWRM_FUNC_LAG_MODE_QCFG UINT32_C(0x1af) + /* The command is used to create a link aggr group. */ + #define HWRM_FUNC_LAG_CREATE UINT32_C(0x1b0) + /* The command is used to update a link aggr group. */ + #define HWRM_FUNC_LAG_UPDATE UINT32_C(0x1b1) + /* The command is used to free a link aggr group. */ + #define HWRM_FUNC_LAG_FREE UINT32_C(0x1b2) + /* The command is used to query a link aggr group. */ + #define HWRM_FUNC_LAG_QCFG UINT32_C(0x1b3) + /* This command is use to add TimeTX packet pacing rate. */ + #define HWRM_FUNC_TIMEDTX_PACING_RATE_ADD UINT32_C(0x1c2) + /* + * This command is use to delete TimeTX packet pacing rate + * from the rate table. + */ + #define HWRM_FUNC_TIMEDTX_PACING_RATE_DELETE UINT32_C(0x1c3) + /* + * This command is used to retrieve all the TimeTX pacing rates + * from the rate table that have been added for the function. + */ + #define HWRM_FUNC_TIMEDTX_PACING_RATE_QUERY UINT32_C(0x1c4) /* Experimental */ #define HWRM_SELFTEST_QLIST UINT32_C(0x200) /* Experimental */ #define HWRM_SELFTEST_EXEC UINT32_C(0x201) /* Experimental */ #define HWRM_SELFTEST_IRQ UINT32_C(0x202) - /* Experimental */ + /* Experimental (deprecated) */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA UINT32_C(0x203) /* Experimental */ #define HWRM_PCIE_QSTATS UINT32_C(0x204) @@ -1202,12 +1300,12 @@ typedef struct cmd_nums { #define HWRM_MFG_SOC_IMAGE UINT32_C(0x20c) /* Retrieves the SoC status and image provisioning information */ #define HWRM_MFG_SOC_QSTATUS UINT32_C(0x20d) - /* Tells the fw to program the seeprom memory */ - #define HWRM_MFG_PARAM_SEEPROM_SYNC UINT32_C(0x20e) - /* Tells the fw to read the seeprom memory */ - #define HWRM_MFG_PARAM_SEEPROM_READ UINT32_C(0x20f) - /* Tells the fw to get the health of seeprom data */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH UINT32_C(0x210) + /* Tells the fw to finalize the critical data (store and lock it) */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE UINT32_C(0x20e) + /* Tells the fw to read the critical data */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_READ UINT32_C(0x20f) + /* Tells the fw to get the health of critical data */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH UINT32_C(0x210) /* * The command is used for certificate provisioning to export a * Certificate Signing Request (CSR) from the device. @@ -1242,6 +1340,59 @@ typedef struct cmd_nums { #define HWRM_MFG_SELFTEST_EXEC UINT32_C(0x217) /* Queries the generic stats */ #define HWRM_STAT_GENERIC_QSTATS UINT32_C(0x218) + /* + * The command is used for certificate provisioning to export a + * certificate chain from the device. + */ + #define HWRM_MFG_PRVSN_EXPORT_CERT UINT32_C(0x219) + /* Query the statistics for doorbell drops due to various error conditions. */ + #define HWRM_STAT_DB_ERROR_QSTATS UINT32_C(0x21a) + /* + * The command is used to enable/disable the power on ethernet for + * a particular I/O expander port. + */ + #define HWRM_PORT_POE_CFG UINT32_C(0x230) + /* + * The command is used to query whether the power on ethernet + * is enabled/disabled for a particular I/O expander port. + */ + #define HWRM_PORT_POE_QCFG UINT32_C(0x231) + /* + * This command returns the capabilities related to User Defined + * Congestion Control on a function. + */ + #define HWRM_UDCC_QCAPS UINT32_C(0x258) + /* This command configures User Defined Congestion Control on a function. */ + #define HWRM_UDCC_CFG UINT32_C(0x259) + /* + * This command queries the configuration of User Defined Congestion + * Control on a function. + */ + #define HWRM_UDCC_QCFG UINT32_C(0x25a) + /* This command configures an existing UDCC session. */ + #define HWRM_UDCC_SESSION_CFG UINT32_C(0x25b) + /* This command queries the configuration of a UDCC session. */ + #define HWRM_UDCC_SESSION_QCFG UINT32_C(0x25c) + /* This command queries the UDCC session. */ + #define HWRM_UDCC_SESSION_QUERY UINT32_C(0x25d) + /* This command configures the computation unit. */ + #define HWRM_UDCC_COMP_CFG UINT32_C(0x25e) + /* This command queries the configuration of the computation unit. */ + #define HWRM_UDCC_COMP_QCFG UINT32_C(0x25f) + /* This command queries the status and statistics of the computation unit. */ + #define HWRM_UDCC_COMP_QUERY UINT32_C(0x260) + /* + * This command is used to query the pfc watchdog max configurable + * timeout value. + */ + #define HWRM_QUEUE_PFCWD_TIMEOUT_QCAPS UINT32_C(0x261) + /* This command is used to set the PFC watchdog timeout value. */ + #define HWRM_QUEUE_PFCWD_TIMEOUT_CFG UINT32_C(0x262) + /* + * This command is used to query the current configured pfc watchdog + * timeout value. + */ + #define HWRM_QUEUE_PFCWD_TIMEOUT_QCFG UINT32_C(0x263) /* Experimental */ #define HWRM_TF UINT32_C(0x2bc) /* Experimental */ @@ -1249,8 +1400,6 @@ typedef struct cmd_nums { /* Experimental */ #define HWRM_TF_SESSION_OPEN UINT32_C(0x2c6) /* Experimental */ - #define HWRM_TF_SESSION_ATTACH UINT32_C(0x2c7) - /* Experimental */ #define HWRM_TF_SESSION_REGISTER UINT32_C(0x2c8) /* Experimental */ #define HWRM_TF_SESSION_UNREGISTER UINT32_C(0x2c9) @@ -1279,22 +1428,6 @@ typedef struct cmd_nums { /* Experimental */ #define HWRM_TF_TBL_TYPE_BULK_GET UINT32_C(0x2dc) /* Experimental */ - #define HWRM_TF_CTXT_MEM_ALLOC UINT32_C(0x2e2) - /* Experimental */ - #define HWRM_TF_CTXT_MEM_FREE UINT32_C(0x2e3) - /* Experimental */ - #define HWRM_TF_CTXT_MEM_RGTR UINT32_C(0x2e4) - /* Experimental */ - #define HWRM_TF_CTXT_MEM_UNRGTR UINT32_C(0x2e5) - /* Experimental */ - #define HWRM_TF_EXT_EM_QCAPS UINT32_C(0x2e6) - /* Experimental */ - #define HWRM_TF_EXT_EM_OP UINT32_C(0x2e7) - /* Experimental */ - #define HWRM_TF_EXT_EM_CFG UINT32_C(0x2e8) - /* Experimental */ - #define HWRM_TF_EXT_EM_QCFG UINT32_C(0x2e9) - /* Experimental */ #define HWRM_TF_EM_INSERT UINT32_C(0x2ea) /* Experimental */ #define HWRM_TF_EM_DELETE UINT32_C(0x2eb) @@ -1318,6 +1451,14 @@ typedef struct cmd_nums { #define HWRM_TF_IF_TBL_SET UINT32_C(0x2fe) /* Experimental */ #define HWRM_TF_IF_TBL_GET UINT32_C(0x2ff) + /* Experimental */ + #define HWRM_TF_RESC_USAGE_SET UINT32_C(0x300) + /* Experimental */ + #define HWRM_TF_RESC_USAGE_QUERY UINT32_C(0x301) + /* Truflow command to allocate a table */ + #define HWRM_TF_TBL_TYPE_ALLOC UINT32_C(0x302) + /* Truflow command to free a table */ + #define HWRM_TF_TBL_TYPE_FREE UINT32_C(0x303) /* TruFlow command to check firmware table scope capabilities. */ #define HWRM_TFC_TBL_SCOPE_QCAPS UINT32_C(0x380) /* TruFlow command to allocate a table scope ID and create the pools. */ @@ -1330,9 +1471,9 @@ typedef struct cmd_nums { #define HWRM_TFC_TBL_SCOPE_FID_ADD UINT32_C(0x384) /* TruFlow command to remove a FID from a table scope. */ #define HWRM_TFC_TBL_SCOPE_FID_REM UINT32_C(0x385) - /* TruFlow command to allocate a table scope pool. */ + /* DEPRECATED */ #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC UINT32_C(0x386) - /* TruFlow command to free a table scope pool. */ + /* DEPRECATED */ #define HWRM_TFC_TBL_SCOPE_POOL_FREE UINT32_C(0x387) /* Experimental */ #define HWRM_TFC_SESSION_ID_ALLOC UINT32_C(0x388) @@ -1366,8 +1507,20 @@ typedef struct cmd_nums { #define HWRM_TFC_TCAM_ALLOC_SET UINT32_C(0x396) /* TruFlow command to free a TCAM entry. */ #define HWRM_TFC_TCAM_FREE UINT32_C(0x397) + /* Truflow command to set an interface table entry */ + #define HWRM_TFC_IF_TBL_SET UINT32_C(0x398) + /* Truflow command to get an interface table entry */ + #define HWRM_TFC_IF_TBL_GET UINT32_C(0x399) + /* TruFlow command to get configured info about a table scope. */ + #define HWRM_TFC_TBL_SCOPE_CONFIG_GET UINT32_C(0x39a) + /* TruFlow command to query the resource usage state. */ + #define HWRM_TFC_RESC_USAGE_QUERY UINT32_C(0x39b) /* Experimental */ #define HWRM_SV UINT32_C(0x400) + /* Run a PCIe or Ethernet serdes test and retrieve test data. */ + #define HWRM_DBG_SERDES_TEST UINT32_C(0xff0e) + /* Flush any trace buffer data that has not been sent to the host. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH UINT32_C(0xff0f) /* Experimental */ #define HWRM_DBG_READ_DIRECT UINT32_C(0xff10) /* Experimental */ @@ -1423,6 +1576,20 @@ typedef struct cmd_nums { #define HWRM_DBG_USEQ_DELIVERY_REQ UINT32_C(0xff2a) /* Experimental */ #define HWRM_DBG_USEQ_RESP_HDR UINT32_C(0xff2b) + /* + * This command is used to request the firmware to store a coredump + * into Host memory previously specified with the + * HWRM_DBG_CRASHDUMP_MEDIUM_CFG API + */ + #define HWRM_DBG_COREDUMP_CAPTURE UINT32_C(0xff2c) + #define HWRM_DBG_PTRACE UINT32_C(0xff2d) + /* + * This command is used to request the firmware to simulate cable insert + * or removal. + */ + #define HWRM_DBG_SIM_CABLE_STATE UINT32_C(0xff2e) + #define HWRM_NVM_GET_VPD_FIELD_INFO UINT32_C(0xffea) + #define HWRM_NVM_SET_VPD_FIELD_INFO UINT32_C(0xffeb) #define HWRM_NVM_DEFRAG UINT32_C(0xffec) #define HWRM_NVM_REQ_ARBITRATION UINT32_C(0xffed) /* Experimental */ @@ -1518,14 +1685,14 @@ typedef struct ret_codes { #define HWRM_ERR_CODE_NO_FLOW_COUNTER_DURING_ALLOC UINT32_C(0xc) /* * This error code is only reported by firmware when the registered - * driver instances requested to offloaded a flow but was unable to because - * the requested key's hash collides with the installed keys. + * driver instances requested to offloaded a flow but was unable to + * because the requested key's hash collides with the installed keys. */ #define HWRM_ERR_CODE_KEY_HASH_COLLISION UINT32_C(0xd) /* * This error code is only reported by firmware when the registered - * driver instances requested to offloaded a flow but was unable to because - * the same key has already been installed. + * driver instances requested to offloaded a flow but was unable to + * because the same key has already been installed. */ #define HWRM_ERR_CODE_KEY_ALREADY_EXISTS UINT32_C(0xe) /* @@ -1534,8 +1701,8 @@ typedef struct ret_codes { */ #define HWRM_ERR_CODE_HWRM_ERROR UINT32_C(0xf) /* - * Firmware is unable to service the request at the present time. Caller - * may try again later. + * Firmware is unable to service the request at the present time. + * Caller may try again later. */ #define HWRM_ERR_CODE_BUSY UINT32_C(0x10) /* @@ -1551,6 +1718,11 @@ typedef struct ret_codes { */ #define HWRM_ERR_CODE_PF_UNAVAILABLE UINT32_C(0x12) /* + * This error code is reported by Firmware when the specific entity + * requested by the host is not present or does not exist. + */ + #define HWRM_ERR_CODE_ENTITY_NOT_PRESENT UINT32_C(0x13) + /* * This value indicates that the HWRM response is in TLV format and * should be interpreted as one or more TLVs starting with the * hwrm_resp_hdr TLV. This value is not an indication of any error @@ -1587,11 +1759,12 @@ typedef struct ret_codes { ((x) == 0x10 ? "BUSY": \ ((x) == 0x11 ? "RESOURCE_LOCKED": \ ((x) == 0x12 ? "PF_UNAVAILABLE": \ - "Unknown decode" ))))))))))))))))))) : \ + ((x) == 0x13 ? "ENTITY_NOT_PRESENT": \ + "Unknown decode" )))))))))))))))))))) : \ (((x) < 0x8080) ? \ ((x) == 0x8000 ? "TLV_ENCAPSULATED_RESPONSE": \ "Unknown decode" ) : \ - (((x) <= 0xffff) ? \ + (((x) <= UINT16_MAX) ? \ ((x) == 0xfffe ? "UNKNOWN_ERR": \ ((x) == 0xffff ? "CMD_NOT_SUPPORTED": \ "Unknown decode" )) : \ @@ -1614,7 +1787,7 @@ typedef struct hwrm_err_output { /* This field provides original sequence number of the command. */ uint16_t seq_id; /* - * This field is the length of the response in bytes. The + * This field is the length of the response in bytes. The * last byte of the response is a valid flag that will read * as '1' when the command has been completely written to * memory. @@ -1631,9 +1804,9 @@ typedef struct hwrm_err_output { uint8_t cmd_err; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -1644,7 +1817,12 @@ typedef struct hwrm_err_output { * applicable (All F's). Need to cast it the size of the field if needed. */ #define HWRM_NA_SIGNATURE ((uint32_t)(-1)) -/* hwrm_func_buf_rgtr */ +/* + * This is reflecting the size of the PF mailbox and not the maximum + * command size for any of the HWRM command structures. To determine + * the maximum size of an HWRM command supported by the firmware, see + * the max_ext_req_len field in the response of the HWRM_VER_GET command. + */ #define HWRM_MAX_REQ_LEN 128 /* hwrm_cfa_flow_info */ #define HWRM_MAX_RESP_LEN 704 @@ -1668,10 +1846,10 @@ typedef struct hwrm_err_output { #define HWRM_TARGET_ID_TOOLS 0xFFFD #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 -#define HWRM_VERSION_UPDATE 2 +#define HWRM_VERSION_UPDATE 3 /* non-zero means beta version */ -#define HWRM_VERSION_RSVD 136 -#define HWRM_VERSION_STR "1.10.2.136" +#define HWRM_VERSION_RSVD 61 +#define HWRM_VERSION_STR "1.10.3.61" /**************** * hwrm_ver_get * @@ -1887,47 +2065,52 @@ typedef struct hwrm_ver_get_output { /* * If set to 1, then the KONG host mailbox channel is supported. * If set to 0, then the KONG host mailbox channel is not supported. - * By default, this flag should be 0 for older version of core firmware. + * By default, this flag should be 0 for older version of core + * firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED UINT32_C(0x10) /* - * If set to 1, then the 64bit flow handle is supported in addition to the - * legacy 16bit flow handle. If set to 0, then the 64bit flow handle is not - * supported. By default, this flag should be 0 for older version of core firmware. + * If set to 1, then the 64bit flow handle is supported in addition + * to the legacy 16bit flow handle. If set to 0, then the 64bit flow + * handle is not supported. By default, this flag should be 0 for + * older version of core firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED UINT32_C(0x20) /* - * If set to 1, then filter type can be provided in filter_alloc or filter_cfg - * filter types like L2 for l2 traffic and ROCE for roce & l2 traffic. - * If set to 0, then filter types not supported. - * By default, this flag should be 0 for older version of core firmware. + * If set to 1, then filter type can be provided in filter_alloc or + * filter_cfg filter types like L2 for l2 traffic and ROCE for roce & + * l2 traffic. If set to 0, then filter types not supported. By + * default, this flag should be 0 for older version of core firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_L2_FILTER_TYPES_ROCE_OR_L2_SUPPORTED UINT32_C(0x40) /* - * If set to 1, firmware is capable to support virtio vSwitch offload model. - * If set to 0, firmware can't supported virtio vSwitch offload model. - * By default, this flag should be 0 for older version of core firmware. + * If set to 1, firmware is capable to support virtio vSwitch offload + * model. If set to 0, firmware can't supported virtio vSwitch + * offload model. + * By default, this flag should be 0 for older version of core + * firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_VIRTIO_VSWITCH_OFFLOAD_SUPPORTED UINT32_C(0x80) /* * If set to 1, firmware is capable to support trusted VF. * If set to 0, firmware is not capable to support trusted VF. - * By default, this flag should be 0 for older version of core firmware. + * By default, this flag should be 0 for older version of core + * firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED UINT32_C(0x100) /* * If set to 1, firmware is capable to support flow aging. * If set to 0, firmware is not capable to support flow aging. - * By default, this flag should be 0 for older version of core firmware. - * (deprecated) + * By default, this flag should be 0 for older version of core + * firmware. (deprecated) */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_FLOW_AGING_SUPPORTED UINT32_C(0x200) /* - * If set to 1, firmware is capable to support advanced flow counters like, - * Meter drop counters and EEM counters. - * If set to 0, firmware is not capable to support advanced flow counters. - * By default, this flag should be 0 for older version of core firmware. - * (deprecated) + * If set to 1, firmware is capable to support advanced flow counters + * like, Meter drop counters and EEM counters. + * If set to 0, firmware is not capable to support advanced flow + * counters. By default, this flag should be 0 for older version of + * core firmware. (deprecated) */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_ADV_FLOW_COUNTERS_SUPPORTED UINT32_C(0x400) /* @@ -1935,28 +2118,30 @@ typedef struct hwrm_ver_get_output { * Extended Exact Match(EEM) feature. * If set to 0, firmware is not capable to support the use of the * CFA EEM feature. - * By default, this flag should be 0 for older version of core firmware. - * (deprecated) + * By default, this flag should be 0 for older version of core + * firmware. (deprecated) */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_EEM_SUPPORTED UINT32_C(0x800) /* - * If set to 1, the firmware is able to support advance CFA flow management - * features reported in the HWRM_CFA_FLOW_MGNT_QCAPS. - * If set to 0, then the firmware doesn’t support the advance CFA flow management - * features. - * By default, this flag should be 0 for older version of core firmware. + * If set to 1, the firmware is able to support advance CFA flow + * management features reported in the HWRM_CFA_FLOW_MGNT_QCAPS. + * If set to 0, then the firmware doesn't support the advance CFA + * flow management features. + * By default, this flag should be 0 for older version of core + * firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED UINT32_C(0x1000) /* * Deprecated and replaced with cfa_truflow_supported. * If set to 1, the firmware is able to support TFLIB features. - * If set to 0, then the firmware doesn’t support TFLIB features. - * By default, this flag should be 0 for older version of core firmware. + * If set to 0, then the firmware doesn't support TFLIB features. + * By default, this flag should be 0 for older version of core + * firmware. */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_TFLIB_SUPPORTED UINT32_C(0x2000) /* * If set to 1, the firmware is able to support TruFlow features. - * If set to 0, then the firmware doesn’t support TruFlow features. + * If set to 0, then the firmware doesn't support TruFlow features. * By default, this flag should be 0 for older version of * core firmware. */ @@ -1967,6 +2152,13 @@ typedef struct hwrm_ver_get_output { */ #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SECURE_BOOT_CAPABLE UINT32_C(0x8000) /* + * If set to 1, then firmware is able to support the secure solution + * feature. + * If set to 0, then firmware does not support the secure solution + * feature. + */ + #define HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SECURE_SOC_CAPABLE UINT32_C(0x10000) + /* * This field represents the major version of RoCE firmware. * A change in major version represents a major release. */ @@ -2018,7 +2210,10 @@ typedef struct hwrm_ver_get_output { uint8_t chip_metal; /* This field returns the bond id of the chip. */ uint8_t chip_bond_id; - /* This value indicates the type of platform used for chip implementation. */ + /* + * This value indicates the type of platform used for chip + * implementation. + */ uint8_t chip_platform_type; /* ASIC */ #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_ASIC UINT32_C(0x0) @@ -2071,8 +2266,8 @@ typedef struct hwrm_ver_get_output { * host drivers that it has not completed resource initialization * required for data path operations. Host drivers should not send * any HWRM command that requires data path resources. Firmware will - * fail those commands with HWRM_ERR_CODE_BUSY. Host drivers can retry - * those commands once both the flags are cleared. + * fail those commands with HWRM_ERR_CODE_BUSY. Host drivers can + * retry those commands once both the flags are cleared. * If this flag and dev_not_rdy flag are set to 0, device is ready * to accept all HWRM commands. */ @@ -2232,9 +2427,9 @@ typedef struct hwrm_ver_get_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -2801,11 +2996,11 @@ typedef struct crypto_presync_bd_cmd { * Typically, presync BDs are used for packet retransmissions. Source * port sends all the packets in order over the network to destination * port and packets get dropped in the network. The destination port - * will request retranmission of dropped packets and source port driver - * will send presync BD to setup the transmitter appropriately. It will - * provide the start and end TCP sequence number of the data to be - * transmitted. HW keeps two sets of context variable, one for in order - * traffic and one for retransmission traffic. HW is designed to + * will request retransmission of dropped packets and source port + * driver will send presync BD to setup the transmitter appropriately. + * It will provide the start and end TCP sequence number of the data to + * be transmitted. HW keeps two sets of context variable, one for in + * order traffic and one for retransmission traffic. HW is designed to * transmit everything posted in the presync BD and return to in order * mode after that. No inorder context variables are updated in the * process. There is a special case where packets can be dropped @@ -2955,22 +3150,22 @@ typedef struct ce_bds_quic_add_data_msg { * exchanged as part of sessions setup between the two end * points for QUIC operations. */ - uint64_t quic_iv_lo; + uint8_t quic_iv_lo[8]; /* * Most-significant 32 bits (of 96) of additional IV that is * exchanged as part of sessions setup between the two end * points for QUIC operations. */ - uint32_t quic_iv_hi; + uint8_t quic_iv_hi[4]; uint32_t unused_1; /* * Key used for encrypting or decrypting records. The Key is exchanged * as part of sessions setup between the two end points through this * mid-path BD. */ - uint32_t session_key[8]; + uint8_t session_key[32]; /* Header protection key. */ - uint32_t hp_key[8]; + uint8_t hp_key[32]; /* Packet number associated with the QUIC connection. */ uint64_t pkt_number; } ce_bds_quic_add_data_msg_t, *pce_bds_quic_add_data_msg_t; @@ -3359,7 +3554,7 @@ typedef struct tx_bd_long_hi { * 0xffff. * * If set to one when LSO is '1', then the IPID will be treated - * as a 15b number and will be wrapped if it exceeds a value 0f + * as a 15b number and will be wrapped if it exceeds a value of * 0x7fff. */ #define TX_BD_LONG_LFLAGS_IPID_FMT UINT32_C(0x40) @@ -3418,7 +3613,7 @@ typedef struct tx_bd_long_hi { * will be the following behavior for all cases independent of * settings of inner LSO and checksum offload BD flags. * If outer UDP checksum is 0, then do not update it. - * If outer UDP checksum is non zero, then the hardware should + * If outer UDP checksum is non zero, then the hardware should * compute and update it. */ #define TX_BD_LONG_LFLAGS_OT_IP_CHKSUM UINT32_C(0x2000) @@ -3554,7 +3749,7 @@ typedef struct tx_bd_long_hi { * - Wh+/SR - this option is not supported. * - Thor - cfa_meta[15:0] is used for metadata output if en_bd_meta * is set in the Lookup Table. - * - SR2 - {4’d0, cfa_meta[27:0]} is used for metadata output if + * - SR2 - {4'd0, cfa_meta[27:0]} is used for metadata output if * en_bd_meta is set in the Lookup Table. */ #define TX_BD_LONG_CFA_META_KEY_METADATA_TRANSFER (UINT32_C(0x2) << 28) @@ -3859,7 +4054,7 @@ typedef struct tx_bd_long_inline { * - Wh+/SR - this option is not supported. * - Thor - cfa_meta[15:0] is used for metadata output if en_bd_meta * is set in the Lookup Table. - * - SR2 - {4’d0, cfa_meta[27:0]} is used for metadata output if + * - SR2 - {4'd0, cfa_meta[27:0]} is used for metadata output if * en_bd_meta is set in the Lookup Table. */ #define TX_BD_LONG_INLINE_CFA_META_KEY_METADATA_TRANSFER (UINT32_C(0x2) << 28) @@ -3987,6 +4182,95 @@ typedef struct tx_bd_presync_cmd { uint32_t unused_1; } tx_bd_presync_cmd_t, *ptx_bd_presync_cmd_t; +/* + * This structure is used to send additional information for transmitting + * packets using timed transmit scheduling. It must only to be applied as + * the second BD of a BD chain that represents a packet. Any subsequent + * BDs will follow the timed transmit BD. + */ +/* tx_bd_timedtx (size:128b/16B) */ + +typedef struct tx_bd_timedtx { + uint16_t flags_type; + /* This value identifies the type of buffer descriptor. */ + #define TX_BD_TIMEDTX_TYPE_MASK UINT32_C(0x3f) + #define TX_BD_TIMEDTX_TYPE_SFT 0 + /* + * Indicates a timed transmit BD. This is a 16b BD that is inserted + * into a packet BD chain immediately after the first BD. It is used + * to control the flow in a timed transmit operation. + */ + #define TX_BD_TIMEDTX_TYPE_TX_BD_TIMEDTX UINT32_C(0xa) + #define TX_BD_TIMEDTX_TYPE_LAST TX_BD_TIMEDTX_TYPE_TX_BD_TIMEDTX + /* Unless otherwise stated, sub-fields of this field are always valid. */ + #define TX_BD_TIMEDTX_FLAGS_MASK UINT32_C(0xffc0) + #define TX_BD_TIMEDTX_FLAGS_SFT 6 + /* + * This value identifies the kind of buffer timed transmit mode that + * is to be enabled for the packet. + */ + #define TX_BD_TIMEDTX_FLAGS_KIND_MASK UINT32_C(0x1c0) + #define TX_BD_TIMEDTX_FLAGS_KIND_SFT 6 + /* + * This timed transmit mode indicates that the packet will be + * scheduled and send immediately (or as soon as possible), once + * it is scheduled in the transmitter. + * Note: This mode is similar to regular (non-timed transmit) + * operation. Its main purpose is to cancel pace mode timed + * transmit. + */ + #define TX_BD_TIMEDTX_FLAGS_KIND_ASAP (UINT32_C(0x0) << 6) + /* + * This timed transmit mode is used to schedule transmission of + * the packet no earlier than the time given in the tx_time + * field of the BD. + * Note: In case subsequent packets don't include a timed transmit + * BD, they will be scheduled subsequently for transmission + * without any timed transmit constraint. + */ + #define TX_BD_TIMEDTX_FLAGS_KIND_SO_TXTIME (UINT32_C(0x1) << 6) + /* + * This timed transmit mode is used to enable rate control for the + * flow (QP) at a rate as defined by the rate field of this BD. + * Note: In case subsequent, adjacent packets on the same flow + * don't include a timed transmit BD, they will continue to be + * paced by the transmitter at the same rate as given in this BD. + */ + #define TX_BD_TIMEDTX_FLAGS_KIND_PACE (UINT32_C(0x2) << 6) + #define TX_BD_TIMEDTX_FLAGS_KIND_LAST TX_BD_TIMEDTX_FLAGS_KIND_PACE + /* + * This field exists in all Tx BDs. It doesn't apply to this particular + * BD type since the BD never represents an SGL or inline data; i.e. it + * is only a command. This field must be zero. + */ + /* + * Note that if this field is not zero, a fatal length error will be + * generated as it will be included in the aggregate of SGE lengths for + * the packet. + */ + uint16_t len; + /* + * This field represents the rate of the flow (QP) in terms of KB/s. + * This applies to pace mode timed transmit. + */ + uint32_t rate; + /* + * Applying this rate to a QP will result in this and all subsequent + * packets of the flow being paced at the given rate, until such time + * that the timed transmit mode is either changed or the rate is + * updated in a future packet on the flow. + * This field is applicable only if flags.kind is pace. + */ + #define TX_BD_TIMEDTX_RATE_VAL_MASK UINT32_C(0x1ffffff) + #define TX_BD_TIMEDTX_RATE_VAL_SFT 0 + /* + * This field represents the nano-second time to transmit the + * corresponding packet using SO_TXTIME mode of timed transmit. + * This field is applicable only if flags.kind is so_txtime. + */ + uint64_t tx_time; +} tx_bd_timedtx_t, *ptx_bd_timedtx_t; + /* rx_prod_pkt_bd (size:128b/16B) */ typedef struct rx_prod_pkt_bd { @@ -6349,7 +6633,19 @@ typedef struct rx_pkt_v3_cmpl { * is not applicable. */ #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_11 (UINT32_C(0xb) << 7) - #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_LAST RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_11 + /* The RSS hash was computed over tunnel context and tunnel ID field. */ + #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_12 (UINT32_C(0xc) << 7) + /* + * The RSS hash was computed over tunnel source IP address, tunnel + * destination IP address, and tunnel ID field. + */ + #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_13 (UINT32_C(0xd) << 7) + /* + * The RSS hash was computed over tunnel source IP address, tunnel + * destination IP address, tunnel context, and tunnel ID field. + */ + #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_14 (UINT32_C(0xe) << 7) + #define RX_PKT_V3_CMPL_RSS_HASH_TYPE_LAST RX_PKT_V3_CMPL_RSS_HASH_TYPE_ENUM_14 uint16_t metadata1_payload_offset; /* * If truncation placement is not used, this value indicates the offset @@ -6619,16 +6915,12 @@ typedef struct rx_pkt_v3_cmpl_hi { */ #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (UINT32_C(0x5) << 9) /* - * Indicates that the IP checksum failed its check in the tunnel - * header. - */ - #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_IP_CS_ERROR (UINT32_C(0x6) << 9) - /* - * Indicates that the L4 checksum failed its check in the tunnel + * Indicates that the physical packet is shorter than that claimed + * by the tunnel header length. Valid for GTPv1-U packets. * header. */ - #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_L4_CS_ERROR (UINT32_C(0x7) << 9) - #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_LAST RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_L4_CS_ERROR + #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_TOTAL_ERROR (UINT32_C(0x6) << 9) + #define RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_LAST RX_PKT_V3_CMPL_HI_ERRORS_T_PKT_ERROR_T_TOTAL_ERROR /* * This indicates that there was an error in the inner * portion of the packet when this @@ -6683,17 +6975,7 @@ typedef struct rx_pkt_v3_cmpl_hi { * for TCP. */ #define RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (UINT32_C(0x8) << 12) - /* - * Indicates that the IP checksum failed its check in the - * inner header. - */ - #define RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_IP_CS_ERROR (UINT32_C(0x9) << 12) - /* - * Indicates that the L4 checksum failed its check in the - * inner header. - */ - #define RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_L4_CS_ERROR (UINT32_C(0xa) << 12) - #define RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_LAST RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_L4_CS_ERROR + #define RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_LAST RX_PKT_V3_CMPL_HI_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN /* * This is data from the CFA block as indicated by the meta_format * field. @@ -7623,7 +7905,7 @@ typedef struct rx_tpa_start_v2_cmpl_hi { #define RX_TPA_START_V2_CMPL_FLAGS2_IP_TYPE UINT32_C(0x100) /* * This indicates that the complete 1's complement checksum was - * calculated for the packet in the affregation. + * calculated for the packet in the aggregation. */ #define RX_TPA_START_V2_CMPL_FLAGS2_COMPLETE_CHECKSUM_CALC UINT32_C(0x200) /* @@ -8602,7 +8884,7 @@ typedef struct rx_tpa_v2_start_cmpl_hi { /* This value indicates what format the metadata field is. */ #define RX_TPA_V2_START_CMPL_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0) #define RX_TPA_V2_START_CMPL_FLAGS2_META_FORMAT_SFT 4 - /* No metadata informtaion. Value is zero. */ + /* No metadata information. Value is zero. */ #define RX_TPA_V2_START_CMPL_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4) /* * The metadata field contains the VLAN tag and TPID value. @@ -8619,7 +8901,7 @@ typedef struct rx_tpa_v2_start_cmpl_hi { * - VXLAN = VNI[23:0] -> VXLAN Network ID * - Geneve (NGE) = VNI[23:0] a-> Virtual Network Identifier. * - NVGRE = TNI[23:0] -> Tenant Network ID - * - GRE = KEY[31:0 -> key fieled with bit mask. zero if K = 0 + * - GRE = KEY[31:0] -> key field with bit mask. Zero if K = 0 * - IPV4 = 0 (not populated) * - IPV6 = Flow Label[19:0] * - PPPoE = sessionID[15:0] @@ -9511,7 +9793,7 @@ typedef struct hwrm_async_event_cmpl { */ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_THRESHOLD UINT32_C(0x46) /* - * An event from firmware indicating that the RSS capabilites have + * An event from firmware indicating that the RSS capabilities have * changed. */ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RSS_CHANGE UINT32_C(0x47) @@ -9529,8 +9811,47 @@ typedef struct hwrm_async_event_cmpl { * doorbell copy region. */ #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HW_DOORBELL_RECOVERY_READ_ERROR UINT32_C(0x49) + /* + * An event from firmware indicating that the XID partition was not + * allocated/freed by the FW successfully for the request that is + * encapsulated in the HWRM_EXEC_FWD_RESP by the PF driver for VF. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_CTX_ERROR UINT32_C(0x4a) + /* + * A UDCC session has been modified in the FW. The session_id can be + * used by the driver to retrieve information related to the UDCC + * session. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_UDCC_SESSION_CHANGE UINT32_C(0x4b) + /* + * Used to notify the host that the firmware has DMA-ed additional + * debug data to the host buffer. This is effectively a producer index + * update. The host driver can utilize this information to determine + * how much of its host buffer has been populated by the firmware. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER UINT32_C(0x4c) + /* + * Memory mapping between GPA and HPA has been configured for + * a peer device. Inform driver to pick up the new mapping. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PEER_MMAP_CHANGE UINT32_C(0x4d) + /* + * Used to notify representor endpoint in the driver about pair creation + * in the firmware. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_REPRESENTOR_PAIR_CHANGE UINT32_C(0x4e) + /* + * VF statistics context change. Informs PF driver that a VF + * statistics context has either been allocated or freed. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_STAT_CHANGE UINT32_C(0x4f) + /* + * coredump collection into host DMA address. Informs PF driver that + * the coredump has been captured. + */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HOST_COREDUMP UINT32_C(0x50) /* Maximum Registrable event id. */ - #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_MAX_RGTR_EVENT_ID UINT32_C(0x4a) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_MAX_RGTR_EVENT_ID UINT32_C(0x51) /* * A trace log message. This contains firmware trace logs string * embedded in the asynchronous message. This is an experimental @@ -9604,8 +9925,15 @@ typedef struct hwrm_async_event_cmpl { ((x) == 0x47 ? "RSS_CHANGE": \ ((x) == 0x48 ? "DOORBELL_PACING_NQ_UPDATE": \ ((x) == 0x49 ? "HW_DOORBELL_RECOVERY_READ_ERROR": \ - ((x) == 0x4a ? "MAX_RGTR_EVENT_ID": \ - "Unknown decode" ))))))))))))))))))))))))))))))))))))))))))) : \ + ((x) == 0x4a ? "CTX_ERROR": \ + ((x) == 0x4b ? "UDCC_SESSION_CHANGE": \ + ((x) == 0x4c ? "DBG_BUF_PRODUCER": \ + ((x) == 0x4d ? "PEER_MMAP_CHANGE": \ + ((x) == 0x4e ? "REPRESENTOR_PAIR_CHANGE": \ + ((x) == 0x4f ? "VF_STAT_CHANGE": \ + ((x) == 0x50 ? "HOST_COREDUMP": \ + ((x) == 0x51 ? "MAX_RGTR_EVENT_ID": \ + "Unknown decode" )))))))))))))))))))))))))))))))))))))))))))))))))) : \ (((x) < 0x100) ? \ ((x) == 0xfe ? "FW_TRACE_MSG": \ ((x) == 0xff ? "HWRM_ERROR": \ @@ -10042,6 +10370,30 @@ typedef struct hwrm_async_event_cmpl_port_phy_cfg_change { #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_ID_PORT_PHY_CFG_CHANGE /* Event specific data */ uint32_t event_data2; + /* + * This value indicates the current status of the optics module on + * this port. the same information can be found in the module_status + * field of the HWRM_PORT_PHY_QCFG response + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_SFT 0 + /* Module is inserted and accepted */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_NONE UINT32_C(0x0) + /* Module is rejected and transmit side Laser is disabled. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_DISABLETX UINT32_C(0x1) + /* Module mismatch warning. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_MISMATCH UINT32_C(0x2) + /* Module is rejected and powered down. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_PWRDOWN UINT32_C(0x3) + /* Module is not inserted. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_NOTINSERTED UINT32_C(0x4) + /* Module is powered down because of over current fault. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_CURRENTFAULT UINT32_C(0x5) + /* Module is overheated. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_OVERHEATED UINT32_C(0x6) + /* Module status is not applicable. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_NOTAPPLICABLE UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_LAST HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA2_MODULE_STATUS_NOTAPPLICABLE uint8_t opaque_v; /* * This value is written by the NIC such that it will be different @@ -10136,7 +10488,7 @@ typedef struct hwrm_async_event_cmpl_reset_notify { * 16-lsb timestamp (100-msec resolution) * The Maximum Firmware Reset bail out value in the order of 100 * milliseconds. The driver instances will use this value to reinitiate - * the registration process again if the core firmware didn’t set the + * the registration process again if the core firmware didn't set the * state bit. */ uint16_t timestamp_hi; @@ -10748,6 +11100,13 @@ typedef struct hwrm_async_event_cmpl_vf_cfg_change { * If set to 0, then this bit should be ignored. */ #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_TRUSTED_VF_CFG_CHANGE UINT32_C(0x10) + /* + * If this bit is set to 1, then the control of VF was relinquished + * back to the firmware flow manager following the function takeover + * by TruFlow. + * If set to 0, then this bit should be ignored. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_TF_OWNERSHIP_RELEASE UINT32_C(0x20) } hwrm_async_event_cmpl_vf_cfg_change_t, *phwrm_async_event_cmpl_vf_cfg_change_t; /* hwrm_async_event_cmpl_llfc_pfc_change (size:128b/16B) */ @@ -11241,8 +11600,8 @@ typedef struct hwrm_async_event_cmpl_quiesce_done { #define HWRM_ASYNC_EVENT_CMPL_QUIESCE_DONE_EVENT_DATA2_OPAQUE_SFT 8 /* * Additional information about internal hardware state related to - * idle/quiesce state. QUIESCE may succeed per quiesce_status - * regardless of idle_state_flags. If QUIESCE fails, the host may + * idle/quiesce state. QUIESCE may succeed per quiesce_status + * regardless of idle_state_flags. If QUIESCE fails, the host may * inspect idle_state_flags to determine whether a retry is warranted. */ #define HWRM_ASYNC_EVENT_CMPL_QUIESCE_DONE_EVENT_DATA2_IDLE_STATE_FLAGS_MASK UINT32_C(0xff0000) @@ -11854,6 +12213,316 @@ typedef struct hwrm_async_event_cmpl_hw_doorbell_recovery_read_error { #define HWRM_ASYNC_EVENT_CMPL_HW_DOORBELL_RECOVERY_READ_ERROR_EVENT_DATA1_READ_ERROR_FLAGS_CQ_ERR UINT32_C(0x8) } hwrm_async_event_cmpl_hw_doorbell_recovery_read_error_t, *phwrm_async_event_cmpl_hw_doorbell_recovery_read_error_t; +/* hwrm_async_event_cmpl_ctx_error (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_ctx_error { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * This async notification message is used to inform the PF driver + * that firmware fails to allocate/free the contexts requested. This + * message is only valid in the XID partition scheme. Given the start + * xid and the number of contexts in error, the PF driver will figure + * out the corresponding XID partition(s) in error. + */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_ID_CTX_ERROR UINT32_C(0x4a) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_ID_CTX_ERROR + /* Event specific data */ + uint32_t event_data2; + /* Context operation code */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_CTX_OP_CODE UINT32_C(0x1) + /* Context alloc failure */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_CTX_OP_CODE_ALLOC UINT32_C(0x0) + /* Context free failure */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_CTX_OP_CODE_FREE UINT32_C(0x1) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_CTX_OP_CODE_LAST HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_CTX_OP_CODE_FREE + /* Number of contexts in error */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_NUM_CTXS_MASK UINT32_C(0xfffe) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_NUM_CTXS_SFT 1 + /* Function ID which the XID partitions are associated with */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_FID_MASK UINT32_C(0xffff0000) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA2_FID_SFT 16 + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* Starting XID that has error */ + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA1_START_XID_MASK UINT32_C(0xffffffff) + #define HWRM_ASYNC_EVENT_CMPL_CTX_ERROR_EVENT_DATA1_START_XID_SFT 0 +} hwrm_async_event_cmpl_ctx_error_t, *phwrm_async_event_cmpl_ctx_error_t; + +/* hwrm_async_event_udcc_session_change (size:128b/16B) */ + +typedef struct hwrm_async_event_udcc_session_change { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_TYPE_LAST HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * This async notification message is used to inform the PF driver + * that firmware has modified a UDCC session. + */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_ID_UDCC_SESSION_CHANGE UINT32_C(0x4b) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_ID_LAST HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_ID_UDCC_SESSION_CHANGE + /* Event specific data */ + uint32_t event_data2; + /* UDCC Session id operation code */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_SFT 0 + /* session_id has been created */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_CREATED UINT32_C(0x0) + /* session_id has been freed */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_FREED UINT32_C(0x1) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_LAST HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA2_SESSION_ID_OP_CODE_FREED + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* UDCC session id which was modified */ + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA1_UDCC_SESSION_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_UDCC_SESSION_CHANGE_EVENT_DATA1_UDCC_SESSION_ID_SFT 0 +} hwrm_async_event_udcc_session_change_t, *phwrm_async_event_udcc_session_change_t; + +/* hwrm_async_event_representor_pair_change (size:128b/16B) */ + +typedef struct hwrm_async_event_representor_pair_change { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_TYPE_LAST HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * This async notification message is used to inform the driver + * that firmware has modified a representor pair. + */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_ID_REPRESENTOR_PAIR_CHANGE UINT32_C(0x4e) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_ID_LAST HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_ID_REPRESENTOR_PAIR_CHANGE + /* Event specific data */ + uint32_t event_data2; + /* Representor pair operation code */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_SFT 0 + /* pair has been created */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_CREATED UINT32_C(0x0) + /* pair has been deleted */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_DELETED UINT32_C(0x1) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_LAST HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_PAIR_OP_CODE_DELETED + /* DSCP insert operation code */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_MASK UINT32_C(0xff00) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_SFT 8 + /* allow dscp modification */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_MODIFY (UINT32_C(0x0) << 8) + /* skip dscp modification */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_IGNORE (UINT32_C(0x1) << 8) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_LAST HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA2_DSCP_OP_CODE_IGNORE + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* Representor endpoint fid which was modified */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA1_PAIR_EP_FID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA1_PAIR_EP_FID_SFT 0 + /* Representor uplink fid which was modified */ + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA1_PAIR_REP_FID_MASK UINT32_C(0xffff0000) + #define HWRM_ASYNC_EVENT_REPRESENTOR_PAIR_CHANGE_EVENT_DATA1_PAIR_REP_FID_SFT 16 +} hwrm_async_event_representor_pair_change_t, *phwrm_async_event_representor_pair_change_t; + +/* hwrm_async_event_cmpl_dbg_buf_producer (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_dbg_buf_producer { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * Used to notify the host that the firmware has DMA-ed additional + * debug data to the host buffer. This is effectively a producer index + * update. The host driver can utilize this information to determine + * how much of its host buffer has been populated by the firmware. + */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER UINT32_C(0x4c) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER + /* Event specific data */ + uint32_t event_data2; + /* + * Specifies the current host buffer offset. Data up to this offset + * has been populated by the firmware. For example, if the firmware + * has DMA-ed 8192 bytes to the host buffer, then this field has a + * value of 8192. This field rolls over to zero once the firmware + * writes the last page of the host buffer + */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURRENT_BUFFER_OFFSET_MASK UINT32_C(0xffffffff) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURRENT_BUFFER_OFFSET_SFT 0 + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_SFT 1 + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* Type of trace buffer that has been updated. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SFT 0 + /* SRT trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT_TRACE UINT32_C(0x0) + /* SRT2 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT2_TRACE UINT32_C(0x1) + /* CRT trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT_TRACE UINT32_C(0x2) + /* CRT2 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT2_TRACE UINT32_C(0x3) + /* RIGP0 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP0_TRACE UINT32_C(0x4) + /* L2 HWRM trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_L2_HWRM_TRACE UINT32_C(0x5) + /* RoCE HWRM trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_ROCE_HWRM_TRACE UINT32_C(0x6) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA0_TRACE UINT32_C(0x7) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA1_TRACE UINT32_C(0x8) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA2_TRACE UINT32_C(0x9) + /* RIGP1 trace. */ + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP1_TRACE UINT32_C(0xa) + #define HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP1_TRACE +} hwrm_async_event_cmpl_dbg_buf_producer_t, *phwrm_async_event_cmpl_dbg_buf_producer_t; + +/* hwrm_async_event_cmpl_peer_mmap_change (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_peer_mmap_change { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * This async notification message is used to inform the driver + * that the memory mapping for a peer device is set. The driver + * will need to query using get_structured_data. + */ + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_EVENT_ID_PEER_MMAP_CHANGE UINT32_C(0x4d) + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_EVENT_ID_PEER_MMAP_CHANGE + /* Event specific data. */ + uint32_t event_data2; + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PEER_MMAP_CHANGE_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; +} hwrm_async_event_cmpl_peer_mmap_change_t, *phwrm_async_event_cmpl_peer_mmap_change_t; + /* hwrm_async_event_cmpl_fw_trace_msg (size:128b/16B) */ typedef struct hwrm_async_event_cmpl_fw_trace_msg { @@ -12036,10 +12705,10 @@ typedef struct hwrm_async_event_cmpl_error_report_base { /* Event specific data */ uint32_t event_data1; /* Indicates the type of error being reported. */ - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK UINT32_C(0xff) #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT 0 /* Reserved */ - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED UINT32_C(0x0) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED UINT32_C(0x0) /* * The NIC was subjected to an extended pause storm which caused it * to disable flow control in order to avoid stalling the Tx path. @@ -12052,7 +12721,7 @@ typedef struct hwrm_async_event_cmpl_error_report_base { * it. The pin number on which this signal was received is stored * in event_data2 as pin_id. */ - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL UINT32_C(0x2) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL UINT32_C(0x2) /* * There was a low level error with an NVM write or erase. * See nvm_err_type for more details. @@ -12063,13 +12732,18 @@ typedef struct hwrm_async_event_cmpl_error_report_base { * threshold is crossed, it indicates one or more doorbells for * the function were dropped by hardware. */ - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD UINT32_C(0x4) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD UINT32_C(0x4) /* * Indicates the NIC's temperature has crossed one of the thermal * thresholds. */ - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD UINT32_C(0x5) - #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD UINT32_C(0x5) + /* + * Speed change not supported with dual rate transceivers + * on this board. + */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DUAL_DATA_RATE_NOT_SUPPORTED UINT32_C(0x6) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DUAL_DATA_RATE_NOT_SUPPORTED } hwrm_async_event_cmpl_error_report_base_t, *phwrm_async_event_cmpl_error_report_base_t; #define GET_ERROR_REPORT_TYPE(x) \ @@ -12080,7 +12754,8 @@ typedef struct hwrm_async_event_cmpl_error_report_base { ((x) == 0x3 ? "NVM": \ ((x) == 0x4 ? "DOORBELL_DROP_THRESHOLD": \ ((x) == 0x5 ? "THERMAL_THRESHOLD": \ - "Unknown decode" )))))) : \ + ((x) == 0x6 ? "DUAL_DATA_RATE_NOT_SUPPORTED": \ + "Unknown decode" ))))))) : \ "Unknown decode" ) @@ -12359,7 +13034,7 @@ typedef struct hwrm_async_event_cmpl_error_report_thermal { #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_ID_ERROR_REPORT /* Event specific data. */ uint32_t event_data2; - /* Current temperature. In Celsius */ + /* Current temperature. In Celsius */ #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK UINT32_C(0xff) #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_SFT 0 /* @@ -12425,6 +13100,168 @@ typedef struct hwrm_async_event_cmpl_error_report_thermal { #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_INCREASING } hwrm_async_event_cmpl_error_report_thermal_t, *phwrm_async_event_cmpl_error_report_thermal_t; +/* hwrm_async_event_cmpl_error_report_dual_data_rate_not_supported (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_error_report_dual_data_rate_not_supported { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * This async notification message is used to inform + * the driver that an error has occurred which may need + * the attention of the administrator. + */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_ID_ERROR_REPORT UINT32_C(0x45) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_ID_ERROR_REPORT + /* Event specific data. */ + uint32_t event_data2; + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* Indicates the type of error being reported. */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_DATA1_ERROR_TYPE_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_DATA1_ERROR_TYPE_SFT 0 + /* + * Speed change not supported with dual rate transceivers + * on this board. + */ + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_DATA1_ERROR_TYPE_DUAL_DATA_RATE_NOT_SUPPORTED UINT32_C(0x6) + #define HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_DATA1_ERROR_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DUAL_DATA_RATE_NOT_SUPPORTED_EVENT_DATA1_ERROR_TYPE_DUAL_DATA_RATE_NOT_SUPPORTED +} hwrm_async_event_cmpl_error_report_dual_data_rate_not_supported_t, *phwrm_async_event_cmpl_error_report_dual_data_rate_not_supported_t; + +/* hwrm_async_event_cmpl_vf_stat_change (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_vf_stat_change { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * VF statistics context change. Informs PF driver that a VF + * statistics context has either been allocated or freed. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_ID_VF_STAT_CHANGE UINT32_C(0x4f) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_ID_VF_STAT_CHANGE + /* Event specific data */ + uint32_t event_data2; + /* + * VF ID that allocated the stats context. This is zero-based and + * relative to each PF. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA2_VF_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA2_VF_ID_SFT 0 + /* + * A value of zero signals to the PF driver that it can free the host + * buffer associated with the statistics context. + * A non-zero values signals to the PF driver that it should allocate + * a host buffer for the statistics context and inform the firmware + * via HWRM_STAT_CTX_ALLOC. The PF driver must provide the sequence id + * in the corresponding HWRM_STAT_CTX_ALLOC request so that firmware + * can correlate it to the VF statistics context. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA2_ACTION_SEQUENCE_ID_MASK UINT32_C(0xffff0000) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA2_ACTION_SEQUENCE_ID_SFT 16 + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; + /* VF statistics context identifier */ + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA1_STAT_CTX_ID_MASK UINT32_C(0xffffffff) + #define HWRM_ASYNC_EVENT_CMPL_VF_STAT_CHANGE_EVENT_DATA1_STAT_CTX_ID_SFT 0 +} hwrm_async_event_cmpl_vf_stat_change_t, *phwrm_async_event_cmpl_vf_stat_change_t; + +/* hwrm_async_event_cmpl_host_coredump (size:128b/16B) */ + +typedef struct hwrm_async_event_cmpl_host_coredump { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_TYPE_LAST HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_TYPE_HWRM_ASYNC_EVENT + /* Identifiers of events. */ + uint16_t event_id; + /* + * coredump collection into host DMA address. Informs PF driver that + * the coredump has been captured. + */ + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_EVENT_ID_HOST_COREDUMP UINT32_C(0x50) + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_EVENT_ID_LAST HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_EVENT_ID_HOST_COREDUMP + /* Event specific data */ + uint32_t event_data2; + uint8_t opaque_v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_HOST_COREDUMP_OPAQUE_SFT 1 + /* 8-lsb timestamp (100-msec resolution) */ + uint8_t timestamp_lo; + /* 16-lsb timestamp (100-msec resolution) */ + uint16_t timestamp_hi; + /* Event specific data */ + uint32_t event_data1; +} hwrm_async_event_cmpl_host_coredump_t, *phwrm_async_event_cmpl_host_coredump_t; + /* metadata_base_msg (size:64b/8B) */ typedef struct metadata_base_msg { @@ -12879,7 +13716,7 @@ typedef struct tx_doorbell { uint32_t key_idx; /* * BD Index of next BD that will be used to transmit data - * on the TX ring mapped to this door bell. NIC may + * on the TX ring mapped to this door bell. NIC may * read and process all BDs up to, but not including this * index. */ @@ -12887,7 +13724,7 @@ typedef struct tx_doorbell { #define TX_DOORBELL_IDX_SFT 0 /* * This value indicates the type of door bell operation - * that is begin requested. This value is '0' for TX + * that is begin requested. This value is '0' for TX * door bell operations. */ #define TX_DOORBELL_KEY_MASK UINT32_C(0xf0000000) @@ -12903,7 +13740,7 @@ typedef struct rx_doorbell { uint32_t key_idx; /* * BD Index of next BD that will be used for an empty receive - * buffer on the RX ring mapped to this door bell. NIC may + * buffer on the RX ring mapped to this door bell. NIC may * read and process all BDs up to, but not including this * index. */ @@ -12911,7 +13748,7 @@ typedef struct rx_doorbell { #define RX_DOORBELL_IDX_SFT 0 /* * This value indicates the type of door bell operation - * that is begin requested. This value is '1' for RX + * that is begin requested. This value is '1' for RX * door bell operations. */ #define RX_DOORBELL_KEY_MASK UINT32_C(0xf0000000) @@ -12935,20 +13772,20 @@ typedef struct cmpl_doorbell { #define CMPL_DOORBELL_IDX_SFT 0 /* * This indicates if the BDIDX value is valid for this - * update when it is '1'. When it is '0', the BDIDX + * update when it is '1'. When it is '0', the BDIDX * value should be ignored. */ #define CMPL_DOORBELL_IDX_VALID UINT32_C(0x4000000) /* * This bit indicates the new interrupt mask state for the - * interrupt associated with the BDIDX. A '1', means the - * interrupt is to be masked. A '0' indicates the interrupt + * interrupt associated with the BDIDX. A '1', means the + * interrupt is to be masked. A '0' indicates the interrupt * is to be unmasked. */ #define CMPL_DOORBELL_MASK UINT32_C(0x8000000) /* * This value indicates the type of door bell operation - * that is begin requested. This value is '2' for CMP + * that is begin requested. This value is '2' for CMP * door bell operations. */ #define CMPL_DOORBELL_KEY_MASK UINT32_C(0xf0000000) @@ -12975,7 +13812,7 @@ typedef struct status_doorbell { #define STATUS_DOORBELL_IDX_SFT 0 /* * This value indicates the type of door bell operation - * that is begin requested. This value is '3' for Status + * that is begin requested. This value is '3' for Status * door bell operations. */ #define STATUS_DOORBELL_KEY_MASK UINT32_C(0xf0000000) @@ -13002,14 +13839,14 @@ typedef struct push32_doorbell { * A value of 1 is invalid since backup must start with a * long 32B BE. * A value of 2 indicates just the first 32B BE. - * A value of 3 indicates 32B+16B BD. etc. + * A value of 3 indicates 32B+16B BD. etc. * A value of 0 indicates 16x16B BD spaces are consumed. */ #define PUSH32_DOORBELL_SZ_MASK UINT32_C(0xf000000) #define PUSH32_DOORBELL_SZ_SFT 24 /* * This value indicates the type of door bell operation - * that is begin requested. This value is 4 for push + * that is begin requested. This value is 4 for push * door bell operations. */ #define PUSH32_DOORBELL_KEY_MASK UINT32_C(0xf0000000) @@ -13036,7 +13873,7 @@ typedef struct push32_doorbell { #define PUSH32_DOORBELL_FLAGS_SFT 6 /* * If set to 1, the packet ends with the data in the buffer - * pointed to by this descriptor. This flag must be + * pointed to by this descriptor. This flag must be * valid on every BD. * * This bit must be set on all push doorbells. @@ -13137,9 +13974,9 @@ typedef struct push32_doorbell { * * This bit must be valid on the first BD of a packet. * - * Packet must be 64B or longer when this flag is set. It is not + * Packet must be 64B or longer when this flag is set. It is not * useful to use this bit with any form of TX offload such as - * CSO or LSO. The intent is that the packet from the host already + * CSO or LSO. The intent is that the packet from the host already * has a valid Ethernet CRC on the packet. */ #define PUSH32_DOORBELL_LFLAGS_NOCRC UINT32_C(0x4) @@ -13156,21 +13993,21 @@ typedef struct push32_doorbell { * of the packet associated with this descriptor. * * For outer UDP checksum, global outer UDP checksum TE_NIC register - * needs to be enabled. If the global outer UDP checksum TE_NIC register - * bit is set, outer UDP checksum will be calculated for the following - * cases: - * 1. Packets with tcp_udp_chksum flag set to offload checksum for inner - * packet AND the inner packet is TCP/UDP. If the inner packet is ICMP for - * example (non-TCP/UDP), even if the tcp_udp_chksum is set, the outer UDP - * checksum will not be calculated. - * 2. Packets with lso flag set which implies inner TCP checksum calculation - * as part of LSO operation. + * needs to be enabled. If the global outer UDP checksum TE_NIC + * register bit is set, outer UDP checksum will be calculated for the + * following cases: + * 1. Packets with tcp_udp_chksum flag set to offload checksum for + * inner packet AND the inner packet is TCP/UDP. If the inner packet is + * ICMP for example (non-TCP/UDP), even if the tcp_udp_chksum is set, + * the outer UDP checksum will not be calculated. + * 2. Packets with lso flag set which implies inner TCP checksum + * calculation as part of LSO operation. */ #define PUSH32_DOORBELL_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) /* * If set to 1, the device will treat this packet with LSO(Large * Send Offload) processing for both normal or encapsulated - * packets, which is a form of TCP segmentation. When this bit + * packets, which is a form of TCP segmentation. When this bit * is 1, the hdr_size and mss fields must be valid. The driver * doesn't need to set t_ip_chksum, ip_chksum, and tcp_udp_chksum * flags since the controller will replace the appropriate @@ -13185,7 +14022,7 @@ typedef struct push32_doorbell { * 0xffff. * * If set to one when LSO is '1', then the IPID will be treated - * as a 15b number and will be wrapped if it exceeds a value 0f + * as a 15b number and will be wrapped if it exceeds a value of * 0x7fff. */ #define PUSH32_DOORBELL_LFLAGS_IPID_FMT UINT32_C(0x40) @@ -13203,12 +14040,12 @@ typedef struct push32_doorbell { #define PUSH32_DOORBELL_LFLAGS_T_IPID UINT32_C(0x80) /* * If set to '1', then the RoCE ICRC will be appended to the - * packet. Packet must be a valid RoCE format packet. + * packet. Packet must be a valid RoCE format packet. */ #define PUSH32_DOORBELL_LFLAGS_ROCE_CRC UINT32_C(0x100) /* * If set to '1', then the FCoE CRC will be appended to the - * packet. Packet must be a valid FCoE format packet. + * packet. Packet must be a valid FCoE format packet. */ #define PUSH32_DOORBELL_LFLAGS_FCOE_CRC UINT32_C(0x200) uint16_t hdr_size; @@ -13291,7 +14128,7 @@ typedef struct push32_doorbell { #define PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28) #define PUSH32_DOORBELL_CFA_META_KEY_LAST PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG /* - * This is the data for the push packet. If the packet + * This is the data for the push packet. If the packet * data does not fit in the first pass, data writing * can continue at offset 4 of the doorbell for up to 4 additional * passes for a total data size of 512B maximum. @@ -13345,8 +14182,8 @@ typedef struct hwrm_func_reset_input { * The ID of the VF that this PF is trying to reset. * Only the parent PF shall be allowed to reset a child VF. * - * A parent PF driver shall use this field only when a specific child VF - * is requested to be reset. + * A parent PF driver shall use this field only when a specific child + * VF is requested to be reset. */ uint16_t vf_id; /* This value indicates the level of a function reset. */ @@ -13392,9 +14229,9 @@ typedef struct hwrm_func_reset_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -13464,16 +14301,16 @@ typedef struct hwrm_func_getfid_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * FID value. This value is used to identify operations on the PCI + * FID value. This value is used to identify operations on the PCI * bus as belonging to a particular PCI function. */ uint16_t fid; uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -13546,9 +14383,9 @@ typedef struct hwrm_func_vf_alloc_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -13622,9 +14459,9 @@ typedef struct hwrm_func_vf_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -13635,7 +14472,7 @@ typedef struct hwrm_func_vf_free_output { ********************/ -/* hwrm_func_vf_cfg_input (size:512b/64B) */ +/* hwrm_func_vf_cfg_input (size:576b/72B) */ typedef struct hwrm_func_vf_cfg_input { /* The HWRM command request type. */ @@ -13671,12 +14508,12 @@ typedef struct hwrm_func_vf_cfg_input { * This bit must be '1' for the mtu field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_MTU UINT32_C(0x1) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_MTU UINT32_C(0x1) /* * This bit must be '1' for the guest_vlan field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_GUEST_VLAN UINT32_C(0x2) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_GUEST_VLAN UINT32_C(0x2) /* * This bit must be '1' for the async_event_cr field to be * configured. @@ -13686,7 +14523,7 @@ typedef struct hwrm_func_vf_cfg_input { * This bit must be '1' for the dflt_mac_addr field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x8) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x8) /* * This bit must be '1' for the num_rsscos_ctxs field to be * configured. @@ -13701,17 +14538,17 @@ typedef struct hwrm_func_vf_cfg_input { * This bit must be '1' for the num_tx_rings field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_TX_RINGS UINT32_C(0x40) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_TX_RINGS UINT32_C(0x40) /* * This bit must be '1' for the num_rx_rings field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_RX_RINGS UINT32_C(0x80) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_RX_RINGS UINT32_C(0x80) /* * This bit must be '1' for the num_l2_ctxs field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_L2_CTXS UINT32_C(0x100) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_L2_CTXS UINT32_C(0x100) /* * This bit must be '1' for the num_vnics field to be * configured. @@ -13721,22 +14558,32 @@ typedef struct hwrm_func_vf_cfg_input { * This bit must be '1' for the num_stat_ctxs field to be * configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_STAT_CTXS UINT32_C(0x400) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_STAT_CTXS UINT32_C(0x400) /* * This bit must be '1' for the num_hw_ring_grps field to be * configured. */ #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_HW_RING_GRPS UINT32_C(0x800) /* - * This bit must be '1' for the num_tx_key_ctxs field to be - * configured. + * This bit must be '1' for the num_ktls_tx_key_ctxs field to + * be configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_TX_KEY_CTXS UINT32_C(0x1000) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_KTLS_TX_KEY_CTXS UINT32_C(0x1000) /* - * This bit must be '1' for the num_rx_key_ctxs field to be - * configured. + * This bit must be '1' for the num_ktls_rx_key_ctxs field to + * be configured. + */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_KTLS_RX_KEY_CTXS UINT32_C(0x2000) + /* + * This bit must be '1' for the num_quic_tx_key_ctxs field to + * be configured. */ - #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_RX_KEY_CTXS UINT32_C(0x2000) + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_QUIC_TX_KEY_CTXS UINT32_C(0x4000) + /* + * This bit must be '1' for the num_quic_rx_key_ctxs field to + * be configured. + */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_NUM_QUIC_RX_KEY_CTXS UINT32_C(0x8000) /* * The maximum transmission unit requested on the function. * The HWRM should make sure that the mtu of @@ -13799,10 +14646,10 @@ typedef struct hwrm_func_vf_cfg_input { #define HWRM_FUNC_VF_CFG_INPUT_FLAGS_RX_ASSETS_TEST UINT32_C(0x2) /* * This bit requests that the firmware test to see if all the assets - * requested in this command (i.e. number of CMPL rings) are available. - * The firmware will return an error if the requested assets are - * not available. The firmware will NOT reserve the assets if they - * are available. + * requested in this command (i.e. number of CMPL rings) are + * available. The firmware will return an error if the requested + * assets are not available. The firmware will NOT reserve the assets + * if they are available. */ #define HWRM_FUNC_VF_CFG_INPUT_FLAGS_CMPL_ASSETS_TEST UINT32_C(0x4) /* @@ -13815,10 +14662,10 @@ typedef struct hwrm_func_vf_cfg_input { #define HWRM_FUNC_VF_CFG_INPUT_FLAGS_RSSCOS_CTX_ASSETS_TEST UINT32_C(0x8) /* * This bit requests that the firmware test to see if all the assets - * requested in this command (i.e. number of ring groups) are available. - * The firmware will return an error if the requested assets are - * not available. The firmware will NOT reserve the assets if they - * are available. + * requested in this command (i.e. number of ring groups) are + * available. The firmware will return an error if the requested + * assets are not available. The firmware will NOT reserve the assets + * if they are available. */ #define HWRM_FUNC_VF_CFG_INPUT_FLAGS_RING_GRP_ASSETS_TEST UINT32_C(0x10) /* @@ -13876,11 +14723,17 @@ typedef struct hwrm_func_vf_cfg_input { uint16_t num_stat_ctxs; /* The number of HW ring groups requested for the VF. */ uint16_t num_hw_ring_grps; - /* Number of Tx Key Contexts requested. */ - uint32_t num_tx_key_ctxs; - /* Number of Rx Key Contexts requested. */ - uint32_t num_rx_key_ctxs; - uint8_t unused[4]; + /* Number of KTLS Tx Key Contexts requested. */ + uint32_t num_ktls_tx_key_ctxs; + /* Number of KTLS Rx Key Contexts requested. */ + uint32_t num_ktls_rx_key_ctxs; + /* The number of MSI-X vectors requested for the VF. */ + uint16_t num_msix; + uint8_t unused[2]; + /* Number of QUIC Tx Key Contexts requested. */ + uint32_t num_quic_tx_key_ctxs; + /* Number of QUIC Rx Key Contexts requested. */ + uint32_t num_quic_rx_key_ctxs; } hwrm_func_vf_cfg_input_t, *phwrm_func_vf_cfg_input_t; /* hwrm_func_vf_cfg_output (size:128b/16B) */ @@ -13897,9 +14750,9 @@ typedef struct hwrm_func_vf_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -13952,7 +14805,7 @@ typedef struct hwrm_func_qcaps_input { uint8_t unused_0[6]; } hwrm_func_qcaps_input_t, *phwrm_func_qcaps_input_t; -/* hwrm_func_qcaps_output (size:768b/96B) */ +/* hwrm_func_qcaps_output (size:1152b/144B) */ typedef struct hwrm_func_qcaps_output { /* The specific error status for the command. */ @@ -13964,7 +14817,7 @@ typedef struct hwrm_func_qcaps_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * FID value. This value is used to identify operations on the PCI + * FID value. This value is used to identify operations on the PCI * bus as belonging to a particular PCI function. */ uint16_t fid; @@ -14095,7 +14948,8 @@ typedef struct hwrm_func_qcaps_output { /* * If the query is for a VF, then this flag shall be ignored, * If this query is for a PF and this flag is set to 1, - * then the PF has the administrative privilege to configure another PF + * then the PF has the administrative privilege to configure another + * PF. */ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ADMIN_PF_SUPPORTED UINT32_C(0x40000) /* @@ -14507,7 +15361,7 @@ typedef struct hwrm_func_qcaps_output { #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_QUIC_SUPPORTED UINT32_C(0x2) /* * When this bit is '1', it indicates that KDNet mode is - * supported on the port for this function. This bit is + * supported on the port for this function. This bit is * never set for a VF. */ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_KDNET_SUPPORTED UINT32_C(0x4) @@ -14562,12 +15416,151 @@ typedef struct hwrm_func_qcaps_output { /* * When this bit is '1', it indicates that the hardware based * link aggregation group (L2 and RoCE) feature is supported. + * This LAG feature is only supported on the THOR2 or newer NIC + * with multiple ports. */ #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_HW_LAG_SUPPORTED UINT32_C(0x400) - #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_ON_CHIP_CTX_SUPPORTED UINT32_C(0x800) - #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_STEERING_TAG_SUPPORTED UINT32_C(0x1000) - #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_ENHANCED_VF_SCALE_SUPPORTED UINT32_C(0x2000) - #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_KEY_XID_PARTITION_SUPPORTED UINT32_C(0x4000) + /* + * When this bit is '1', it indicates all contexts can be stored + * on chip instead of using host based backing store memory. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_ON_CHIP_CTX_SUPPORTED UINT32_C(0x800) + /* + * When this bit is '1', it indicates that the HW supports + * using a steering tag in the memory transactions targeting + * L2 or RoCE ring resources. + * Steering Tags are system-specific values that must follow the + * encoding requirements of the hardware platform. On devices that + * support steering to multiple address domains, a value of 0 in + * bit 0 of the steering tag specifies the address is associated + * with the SOC address space, and a value of 1 indicates the + * address is associated with the host address space. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_STEERING_TAG_SUPPORTED UINT32_C(0x1000) + /* + * When this bit is '1', it indicates that driver can enable + * support for an enhanced VF scale. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_ENHANCED_VF_SCALE_SUPPORTED UINT32_C(0x2000) + /* + * When this bit is '1', it indicates that FW is capable of + * supporting partition based XID management for KTLS/QUIC + * Tx/Rx Key Context types. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_KEY_XID_PARTITION_SUPPORTED UINT32_C(0x4000) + /* + * This bit is only valid on the condition that both + * 'ktls_supported' and 'quic_supported' flags are set. When this + * bit is valid, it conveys information below: + * 1. If it is set to '1', it indicates that the firmware allows the + * driver to run KTLS and QUIC concurrently; + * 2. If it is cleared to '0', it indicates that the driver has to + * make sure all crypto connections on all functions are of the + * same type, i.e., either KTLS or QUIC. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_CONCURRENT_KTLS_QUIC_SUPPORTED UINT32_C(0x8000) + /* + * When this bit is '1', it indicates that the device supports + * setting a cross TC cap on a scheduler queue. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SCHQ_CROSS_TC_CAP_SUPPORTED UINT32_C(0x10000) + /* + * When this bit is '1', it indicates that the device supports + * setting a per TC cap on a scheduler queue. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SCHQ_PER_TC_CAP_SUPPORTED UINT32_C(0x20000) + /* + * When this bit is '1', it indicates that the device supports + * setting a per TC reservation on a scheduler queues. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SCHQ_PER_TC_RESERVATION_SUPPORTED UINT32_C(0x40000) + /* + * When this bit is '1', it indicates that firmware supports query + * for statistics related to invalid doorbell errors and drops. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DB_ERROR_STATS_SUPPORTED UINT32_C(0x80000) + /* + * When this bit is '1', it indicates that the device supports + * VF RoCE resource management. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_ROCE_VF_RESOURCE_MGMT_SUPPORTED UINT32_C(0x100000) + /* + * When this bit is '1', it indicates that the device supports + * UDCC management. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_UDCC_SUPPORTED UINT32_C(0x200000) + /* + * When this bit is '1', it indicates that the device supports Timed + * Transmit TxTime scheduling; this is applicable to L2 flows only. + * It is expected that host software assigns each packet a transmit + * time and posts packets for transmit in time order. NIC hardware + * transmits the packet at time assigned by software. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_TIMED_TX_SO_TXTIME_SUPPORTED UINT32_C(0x400000) + /* + * This bit indicates the method used for the advertisement of the + * max resource limit for the PF and its VFs. + * When this bit is '1', it indicates that the maximum resource + * limits for both RoCE and L2 are software defined. These limits + * are queried using the HWRM backing store qcaps v1 + * and v2(max_num_entries). For RoCE, the resource limits are + * derived from nvm options. For L2, the resources will continue + * to use FW enforced SW limits based on chip config and per PF + * function NVM resource parameters. + * If this bit is '0', the FW will use to legacy behavior. + * For RoCE, the maximum resource values supported by the chip will + * be returned. For L2, the maximum resource values returned will + * be the FW enforced SW limits based on chip config and per PF + * function NVM resource parameters. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_MAX_RESOURCE_LIMITS_SUPPORTED UINT32_C(0x800000) + /* + * When this bit is '1', it indicates that the device supports + * migrating ingress NIC flows to Truflow. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_TF_INGRESS_NIC_FLOW_SUPPORTED UINT32_C(0x1000000) + /* + * When this bit is '1', it indicates that the Firmware supports + * query and clear of the port loopback statistics. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_LPBK_STATS_SUPPORTED UINT32_C(0x2000000) + /* + * When this bit is '1', it indicates that the device supports + * migrating egress NIC flows to Truflow. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_TF_EGRESS_NIC_FLOW_SUPPORTED UINT32_C(0x4000000) + /* + * When this bit is '1', it indicates that the device supports + * multiple lossless CoS queues. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_MULTI_LOSSLESS_QUEUES_SUPPORTED UINT32_C(0x8000000) + /* + * When this bit is '1', it indicates that the firmware supports + * peer memory map storing feature. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_PEER_MMAP_SUPPORTED UINT32_C(0x10000000) + /* + * When this bit is '1', it indicates that the device supports Timed + * Transmit packet pacing; this is applicable to L2 flows only. + * Host software passes the transmit rate of an L2 flow to the + * hardware and hardware uses this rate to derive the transmit time + * for scheduling packet transmission of the flow. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_TIMED_TX_PACING_SUPPORTED UINT32_C(0x20000000) + /* + * When this bit is '1', it indicates that the device supports VF + * statistics ejection. Firmware is capable of copying VF statistics + * to two host buffers - one buffer allocated by VF driver and + * another buffer allocated by the parent PF driver. This bit is + * only set on a PF. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_VF_STAT_EJECTION_SUPPORTED UINT32_C(0x40000000) + /* + * When this bit is '1', it indicates that the parent PF allocated + * the Host DMA buffer to capture the coredump. So that any VF + * driver instance can issue HWRM_DBG_COREDUMP_CAPTURE command + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_HOST_COREDUMP_SUPPORTED UINT32_C(0x80000000) uint16_t tunnel_disable_flag; /* * When this bit is '1', it indicates that the VXLAN parsing @@ -14609,10 +15602,96 @@ typedef struct hwrm_func_qcaps_output { * is disabled in hardware */ #define HWRM_FUNC_QCAPS_OUTPUT_TUNNEL_DISABLE_FLAG_DISABLE_PPPOE UINT32_C(0x80) - uint8_t unused_1; + uint16_t xid_partition_cap; + /* + * When this bit is '1', it indicates that FW is capable of + * supporting partition based XID management for Tx crypto + * key contexts. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_XID_PARTITION_CAP_TX_CK UINT32_C(0x1) + /* + * When this bit is '1', it indicates that FW is capable of + * supporting partition based XID management for Rx crypto + * key contexts. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_XID_PARTITION_CAP_RX_CK UINT32_C(0x2) + /* + * This value uniquely identifies the hardware NIC used by the + * function. The value returned will be the same for all functions. + * A value of 00-00-00-00-00-00-00-00 indicates no device serial number + * is currently configured. This is the same value that is returned by + * PCIe Capability Device Serial Number. + */ + uint8_t device_serial_number[8]; + /* + * This field is only valid in the XID partition mode. It indicates + * the number contexts per partition. + */ + uint16_t ctxs_per_partition; + /* + * The maximum number of tso segments that NIC can handle during the + * large segmentation offload. + * If this field is zero, that means there is no limit on the TSO + * segment limit. + * Note that this field will be zero for older firmware that + * doesn't report the max TSO segment limit. + */ + uint16_t max_tso_segs; + /* + * The maximum number of address vectors that may be allocated across + * all VFs for the function. This is valid only on the PF with VF RoCE + * (SR-IOV) enabled. Returns zero if this command is called on a PF + * with VF RoCE (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_av; + /* + * The maximum number of completion queues that may be allocated across + * all VFs for the function. This is valid only on the PF with VF RoCE + * (SR-IOV) enabled. Returns zero if this command is called on a PF + * with VF RoCE (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_cq; + /* + * The maximum number of memory regions plus memory windows that may be + * allocated across all VFs for the function. This is valid only on the + * PF with VF RoCE (SR-IOV) enabled. Returns zero if this command is + * called on a PF with VF RoCE (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_mrw; + /* + * The maximum number of queue pairs that may be allocated across + * all VFs for the function. This is valid only on the PF with VF RoCE + * (SR-IOV) enabled. Returns zero if this command is called on a PF + * with VF RoCE (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_qp; + /* + * The maximum number of shared receive queues that may be allocated + * across all VFs for the function. This is valid only on the PF with + * VF RoCE (SR-IOV) enabled. Returns zero if this command is called on + * a PF with VF RoCE (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_srq; + /* + * The maximum number of GIDs that may be allocated across all VFs for + * the function. This is valid only on the PF with VF RoCE (SR-IOV) + * enabled. Returns zero if this command is called on a PF with VF RoCE + * (SR-IOV) disabled or on a VF. + */ + uint32_t roce_vf_max_gid; + uint32_t flags_ext3; + /* + * When this bit is '1', firmware supports the driver using + * FUNC_CFG (or FUNC_VF_CFG) to decrease resource reservations + * while some resources are still allocated. An error is returned + * if the driver tries to set the reservation to be less than the + * number of allocated resources. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT3_RM_RSV_WHILE_ALLOC_CAP UINT32_C(0x1) + uint8_t unused_3[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -14668,7 +15747,7 @@ typedef struct hwrm_func_qcfg_input { uint8_t unused_0[6]; } hwrm_func_qcfg_input_t, *phwrm_func_qcfg_input_t; -/* hwrm_func_qcfg_output (size:1024b/128B) */ +/* hwrm_func_qcfg_output (size:1280b/160B) */ typedef struct hwrm_func_qcfg_output { /* The specific error status for the command. */ @@ -14680,7 +15759,7 @@ typedef struct hwrm_func_qcfg_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * FID value. This value is used to identify operations on the PCI + * FID value. This value is used to identify operations on the PCI * bus as belonging to a particular PCI function. */ uint16_t fid; @@ -14747,14 +15826,14 @@ typedef struct hwrm_func_qcfg_output { * If the function that is being queried is a PF, then the HWRM shall * set this field to 0 and the HWRM client shall ignore this field. * If the function that is being queried is a VF, then the HWRM shall - * set this field to 1 if the queried VF is trusted, otherwise the HWRM - * shall set this field to 0. + * set this field to 1 if the queried VF is trusted, otherwise the + * HWRM shall set this field to 0. */ #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_TRUSTED_VF UINT32_C(0x40) /* - * If set to 1, then secure mode is enabled for this function or device. - * If set to 0, then secure mode is disabled (or normal mode) for this - * function or device. + * If set to 1, then secure mode is enabled for this function or + * device. If set to 0, then secure mode is disabled (or normal mode) + * for this function or device. */ #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_SECURE_MODE_ENABLED UINT32_C(0x80) /* @@ -14809,6 +15888,12 @@ typedef struct hwrm_func_qcfg_output { */ #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_ENABLE_RDMA_SRIOV UINT32_C(0x4000) /* + * When set to 1, indicates the field roce_vnic_id in the structure + * is valid. If this bit is 0, the driver should not use the + * 'roce_vnic_id' field. + */ + #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_ROCE_VNIC_ID_VALID UINT32_C(0x8000) + /* * This value is current MAC address configured for this * function. A value of 00-00-00-00-00-00 indicates no * MAC address is currently configured. @@ -14889,10 +15974,10 @@ typedef struct hwrm_func_qcfg_output { #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_UNKNOWN UINT32_C(0xff) #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_LAST HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_UNKNOWN /* - * This field will indicate number of physical functions on this port_partition. - * HWRM shall return unavail (i.e. value of 0) for this field - * when this command is used to query VF's configuration or - * from older firmware that doesn't support this field. + * This field will indicate number of physical functions on this + * port_partition. HWRM shall return unavail (i.e. value of 0) for this + * field when this command is used to query VF's configuration or from + * older firmware that doesn't support this field. */ uint8_t port_pf_cnt; /* number of PFs is not available */ @@ -15000,7 +16085,10 @@ typedef struct hwrm_func_qcfg_output { #define HWRM_FUNC_QCFG_OUTPUT_OPTIONS_LINK_ADMIN_STATE_FORCED_DOWN (UINT32_C(0x0) << 2) /* Admin link state is in forced up mode. */ #define HWRM_FUNC_QCFG_OUTPUT_OPTIONS_LINK_ADMIN_STATE_FORCED_UP (UINT32_C(0x1) << 2) - /* Admin link state is in auto mode - follows the physical link state. */ + /* + * Admin link state is in auto mode - follows the physical link + * state. + */ #define HWRM_FUNC_QCFG_OUTPUT_OPTIONS_LINK_ADMIN_STATE_AUTO (UINT32_C(0x2) << 2) #define HWRM_FUNC_QCFG_OUTPUT_OPTIONS_LINK_ADMIN_STATE_LAST HWRM_FUNC_QCFG_OUTPUT_OPTIONS_LINK_ADMIN_STATE_AUTO /* Reserved for future. */ @@ -15042,7 +16130,7 @@ typedef struct hwrm_func_qcfg_output { */ uint16_t alloc_msix; /* - * The number of registered VF’s associated with the PF. This field + * The number of registered VF's associated with the PF. This field * should be ignored when the request received on the VF interface. * This field will be updated on the PF interface to initiate * the unregister request on PF in the HOT Reset Process. @@ -15050,14 +16138,22 @@ typedef struct hwrm_func_qcfg_output { uint16_t registered_vfs; /* * The size of the doorbell BAR in KBytes reserved for L2 including - * any area that is shared between L2 and RoCE. The L2 driver - * should only map the L2 portion of the doorbell BAR. Any rounding + * any area that is shared between L2 and RoCE. The L2 driver + * should only map the L2 portion of the doorbell BAR. Any rounding * of the BAR size to the native CPU page size should be performed - * by the driver. If the value is zero, no special partitioning + * by the driver. If the value is zero, no special partitioning * of the doorbell BAR between L2 and RoCE is required. */ uint16_t l2_doorbell_bar_size_kb; - uint8_t unused_1; + /* + * A bitmask indicating the active endpoints. Each bit represents a + * specific endpoint, with bit 0 indicating EP 0 and bit 3 indicating + * EP 3. For example: + * - a single root system would return 0x1 + * - a 2x8 system (where EPs 0 and 2 are active) would return 0x5 + * - a 4x4 system (where EPs 0-3 are active) would return 0xF + */ + uint8_t active_endpoints; /* * For backward compatibility this field must be set to 1. * Older drivers might look for this field to be 1 before @@ -15065,21 +16161,22 @@ typedef struct hwrm_func_qcfg_output { */ uint8_t always_1; /* - * This GRC address location is used by the Host driver interfaces to poll - * the adapter ready state to re-initiate the registration process again - * after receiving the RESET Notify event. + * This GRC address location is used by the Host driver interfaces to + * poll the adapter ready state to re-initiate the registration process + * again after receiving the RESET Notify event. */ uint32_t reset_addr_poll; /* - * This field specifies legacy L2 doorbell size in KBytes. Drivers should use - * this value to find out the doorbell page offset from the BAR. + * This field specifies legacy L2 doorbell size in KBytes. Drivers + * should use this value to find out the doorbell page offset from the + * BAR. */ uint16_t legacy_l2_db_size_kb; uint16_t svif_info; /* - * This field specifies the source virtual interface of the function being - * queried. Drivers can use this to program svif field in the L2 context - * table + * This field specifies the source virtual interface of the function + * being queried. Drivers can use this to program svif field in the + * L2 context table */ #define HWRM_FUNC_QCFG_OUTPUT_SVIF_INFO_SVIF_MASK UINT32_C(0x7fff) #define HWRM_FUNC_QCFG_OUTPUT_SVIF_INFO_SVIF_SFT 0 @@ -15141,7 +16238,11 @@ typedef struct hwrm_func_qcfg_output { /* DB page size is 4MB. */ #define HWRM_FUNC_QCFG_OUTPUT_DB_PAGE_SIZE_4MB UINT32_C(0xa) #define HWRM_FUNC_QCFG_OUTPUT_DB_PAGE_SIZE_LAST HWRM_FUNC_QCFG_OUTPUT_DB_PAGE_SIZE_4MB - uint8_t unused_2[2]; + /* + * RoCE VNIC ID for the function. If the function does not have a valid + * RoCE vnic id, then the roce_vnic_id_valid bit in flags is set to 0. + */ + uint16_t roce_vnic_id; /* * Minimum guaranteed bandwidth for the network partition made up * of the caller physical function and all its child virtual @@ -15208,10 +16309,15 @@ typedef struct hwrm_func_qcfg_output { * value is used if ring MTU is not specified. */ uint16_t host_mtu; - uint8_t unused_3[2]; + uint16_t flags2; + /* + * If set to 1, then VF drivers are requested to insert a DSCP + * value into all outgoing L2 packets such that DSCP=VF ID modulo 64 + */ + #define HWRM_FUNC_QCFG_OUTPUT_FLAGS2_SRIOV_DSCP_INSERT_ENABLED UINT32_C(0x1) uint8_t unused_4[2]; /* - * KDNet mode for the port for this function. If a VF, KDNet + * KDNet mode for the port for this function. If a VF, KDNet * mode is always disabled. */ uint8_t port_kdnet_mode; @@ -15226,22 +16332,92 @@ typedef struct hwrm_func_qcfg_output { */ uint8_t kdnet_pcie_function; /* - * Function ID of the KDNET function on this port. If the + * Function ID of the KDNET function on this port. If the * KDNET partition does not exist and the FW supports this * feature, 0xffff will be returned. */ uint16_t port_kdnet_fid; uint8_t unused_5[2]; - /* Number of Tx Key Contexts allocated. */ - uint32_t alloc_tx_key_ctxs; - /* Number of Rx Key Contexts allocated. */ - uint32_t alloc_rx_key_ctxs; - uint8_t unused_6[7]; + /* Number of KTLS Tx Key Contexts allocated. */ + uint32_t num_ktls_tx_key_ctxs; + /* Number of KTLS Rx Key Contexts allocated. */ + uint32_t num_ktls_rx_key_ctxs; + /* + * The LAG idx of this function. The lag_id is per port and the + * valid lag_id is from 0 to 7, if there is no valid lag_id, + * 0xff will be returned. + * This HW lag id is used for Truflow programming only. + */ + uint8_t lag_id; + /* Partition interface for this function. */ + uint8_t parif; + /* + * The LAG ID of a hardware link aggregation group (LAG) whose + * member ports include the port of this function. The LAG was + * previously created using HWRM_FUNC_LAG_CREATE. If the port of this + * function is not a member of any LAG, the fw_lag_id will be 0xff. + */ + uint8_t fw_lag_id; + uint8_t unused_6; + /* Number of QUIC Tx Key Contexts allocated. */ + uint32_t num_quic_tx_key_ctxs; + /* Number of QUIC Rx Key Contexts allocated. */ + uint32_t num_quic_rx_key_ctxs; + /* + * Number of AVs per VF. Only valid for PF. This field is ignored + * when the flag, l2_vf_resource_mgmt, is not set in RoCE + * initialize_fw. + */ + uint32_t roce_max_av_per_vf; + /* + * Number of CQs per VF. Only valid for PF. This field is ignored when + * the flag, l2_vf_resource_mgmt, is not set in RoCE initialize_fw. + */ + uint32_t roce_max_cq_per_vf; + /* + * Number of MR/MWs per VF. Only valid for PF. This field is ignored + * when the flag, l2_vf_resource_mgmt, is not set in RoCE + * initialize_fw. + */ + uint32_t roce_max_mrw_per_vf; + /* + * Number of QPs per VF. Only valid for PF. This field is ignored when + * the flag, l2_vf_resource_mgmt, is not set in RoCE initialize_fw. + */ + uint32_t roce_max_qp_per_vf; + /* + * Number of SRQs per VF. Only valid for PF. This field is ignored + * when the flag, l2_vf_resource_mgmt, is not set in RoCE + * initialize_fw. + */ + uint32_t roce_max_srq_per_vf; + /* + * Number of GIDs per VF. Only valid for PF. This field is ignored + * when the flag, l2_vf_resource_mgmt, is not set in RoCE + * initialize_fw. + */ + uint32_t roce_max_gid_per_vf; + /* + * Bitmap of context types that have XID partition enabled. + * Only valid for PF. + */ + uint16_t xid_partition_cfg; + /* + * When this bit is '1', it indicates that driver enables XID + * partition on Tx crypto key contexts. + */ + #define HWRM_FUNC_QCFG_OUTPUT_XID_PARTITION_CFG_TX_CK UINT32_C(0x1) + /* + * When this bit is '1', it indicates that driver enables XID + * partition on Rx crypto key contexts. + */ + #define HWRM_FUNC_QCFG_OUTPUT_XID_PARTITION_CFG_RX_CK UINT32_C(0x2) + uint8_t unused_7; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -15252,7 +16428,7 @@ typedef struct hwrm_func_qcfg_output { *****************/ -/* hwrm_func_cfg_input (size:1024b/128B) */ +/* hwrm_func_cfg_input (size:1280b/160B) */ typedef struct hwrm_func_cfg_input { /* The HWRM command request type. */ @@ -15345,9 +16521,10 @@ typedef struct hwrm_func_cfg_input { #define HWRM_FUNC_CFG_INPUT_FLAGS_VIRT_MAC_PERSIST UINT32_C(0x800) /* * This bit only applies to the VF. If this bit is set, the statistic - * context counters will not be cleared when the statistic context is freed - * or a function reset is called on VF. This bit will be cleared when the PF - * is unloaded or a function reset is called on the PF. + * context counters will not be cleared when the statistic context is + * freed or a function reset is called on VF. This bit will be + * cleared when the PF is unloaded or a function reset is called on + * the PF. */ #define HWRM_FUNC_CFG_INPUT_FLAGS_NO_AUTOCLEAR_STATISTIC UINT32_C(0x1000) /* @@ -15368,10 +16545,10 @@ typedef struct hwrm_func_cfg_input { #define HWRM_FUNC_CFG_INPUT_FLAGS_RX_ASSETS_TEST UINT32_C(0x4000) /* * This bit requests that the firmware test to see if all the assets - * requested in this command (i.e. number of CMPL rings) are available. - * The firmware will return an error if the requested assets are - * not available. The firmware will NOT reserve the assets if they - * are available. + * requested in this command (i.e. number of CMPL rings) are + * available. The firmware will return an error if the requested + * assets are not available. The firmware will NOT reserve the assets + * if they are available. */ #define HWRM_FUNC_CFG_INPUT_FLAGS_CMPL_ASSETS_TEST UINT32_C(0x8000) /* @@ -15384,10 +16561,10 @@ typedef struct hwrm_func_cfg_input { #define HWRM_FUNC_CFG_INPUT_FLAGS_RSSCOS_CTX_ASSETS_TEST UINT32_C(0x10000) /* * This bit requests that the firmware test to see if all the assets - * requested in this command (i.e. number of ring groups) are available. - * The firmware will return an error if the requested assets are - * not available. The firmware will NOT reserve the assets if they - * are available. + * requested in this command (i.e. number of ring groups) are + * available. The firmware will return an error if the requested + * assets are not available. The firmware will NOT reserve the assets + * if they are available. */ #define HWRM_FUNC_CFG_INPUT_FLAGS_RING_GRP_ASSETS_TEST UINT32_C(0x20000) /* @@ -15492,14 +16669,6 @@ typedef struct hwrm_func_cfg_input { * on this request if the TX_METADATA is enabled for this function. */ #define HWRM_FUNC_CFG_INPUT_FLAGS_BD_METADATA_DISABLE UINT32_C(0x40000000) - /* - * If this bit is set to 1, the driver is requesting FW to see if - * all the assets requested in this command (i.e. number of KTLS/ - * QUIC key contexts) are available. The firmware will return an - * error if the requested assets are not available. The firmware - * will NOT reserve the assets if they are available. - */ - #define HWRM_FUNC_CFG_INPUT_FLAGS_KEY_CTX_ASSETS_TEST UINT32_C(0x80000000) uint32_t enables; /* * This bit must be '1' for the admin_mtu field to be @@ -15653,15 +16822,15 @@ typedef struct hwrm_func_cfg_input { */ #define HWRM_FUNC_CFG_INPUT_ENABLES_HOST_MTU UINT32_C(0x20000000) /* - * This bit must be '1' for the number of Tx Key Contexts - * field to be configured. + * This bit must be '1' for the num_ktls_tx_key_ctxs field to be + * configured. */ - #define HWRM_FUNC_CFG_INPUT_ENABLES_TX_KEY_CTXS UINT32_C(0x40000000) + #define HWRM_FUNC_CFG_INPUT_ENABLES_KTLS_TX_KEY_CTXS UINT32_C(0x40000000) /* - * This bit must be '1' for the number of Rx Key Contexts - * field to be configured. + * This bit must be '1' for the num_ktls_rx_key_ctxs field to be + * configured. */ - #define HWRM_FUNC_CFG_INPUT_ENABLES_RX_KEY_CTXS UINT32_C(0x80000000) + #define HWRM_FUNC_CFG_INPUT_ENABLES_KTLS_RX_KEY_CTXS UINT32_C(0x80000000) /* * This field can be used by the admin PF to configure * mtu of foster PFs. @@ -15853,7 +17022,7 @@ typedef struct hwrm_func_cfg_input { * to configure the EVB mode, it sets the evb_mode_cfg_not_supported * flag in HWRM_FUNC_QCAPS command response for the function. * The HWRM takes into account the switching of EVB mode from one to - * another and reconfigure hardware resources as reqiured. The + * another and reconfigure hardware resources as required. The * switching from VEB to VEPA mode requires the disabling of the * loopback traffic. Additionally, source knockouts are handled * differently in VEB and VEPA modes. @@ -15886,7 +17055,10 @@ typedef struct hwrm_func_cfg_input { #define HWRM_FUNC_CFG_INPUT_OPTIONS_LINK_ADMIN_STATE_FORCED_DOWN (UINT32_C(0x0) << 2) /* Admin state is forced up. */ #define HWRM_FUNC_CFG_INPUT_OPTIONS_LINK_ADMIN_STATE_FORCED_UP (UINT32_C(0x1) << 2) - /* Admin state is in auto mode - is to follow the physical link state. */ + /* + * Admin state is in auto mode - is to follow the physical link + * state. + */ #define HWRM_FUNC_CFG_INPUT_OPTIONS_LINK_ADMIN_STATE_AUTO (UINT32_C(0x2) << 2) #define HWRM_FUNC_CFG_INPUT_OPTIONS_LINK_ADMIN_STATE_LAST HWRM_FUNC_CFG_INPUT_OPTIONS_LINK_ADMIN_STATE_AUTO /* Reserved for future. */ @@ -15903,61 +17075,61 @@ typedef struct hwrm_func_cfg_input { /* * When this bit is '1', the caller requests to enable a MPC * channel with destination to the TX crypto engine block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_TCE_ENABLE UINT32_C(0x1) /* * When this bit is '1', the caller requests to disable a MPC * channel with destination to the TX crypto engine block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_TCE_DISABLE UINT32_C(0x2) /* * When this bit is '1', the caller requests to enable a MPC * channel with destination to the RX crypto engine block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_RCE_ENABLE UINT32_C(0x4) /* * When this bit is '1', the caller requests to disable a MPC * channel with destination to the RX crypto engine block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_RCE_DISABLE UINT32_C(0x8) /* * When this bit is '1', the caller requests to enable a MPC * channel with destination to the TX configurable flow processing - * block. When this bit is ‘0’, this flag has no effect. + * block. When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_TE_CFA_ENABLE UINT32_C(0x10) /* * When this bit is '1', the caller requests to disable a MPC * channel with destination to the TX configurable flow processing - * block. When this bit is ‘0’, this flag has no effect. + * block. When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_TE_CFA_DISABLE UINT32_C(0x20) /* * When this bit is '1', the caller requests to enable a MPC * channel with destination to the RX configurable flow processing - * block. When this bit is ‘0’, this flag has no effect. + * block. When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_RE_CFA_ENABLE UINT32_C(0x40) /* * When this bit is '1', the caller requests to disable a MPC * channel with destination to the RX configurable flow processing - * block. When this bit is ‘0’, this flag has no effect. + * block. When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_RE_CFA_DISABLE UINT32_C(0x80) /* * When this bit is '1', the caller requests to enable a MPC * channel with destination to the primate processor block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_PRIMATE_ENABLE UINT32_C(0x100) /* * When this bit is '1', the caller requests to disable a MPC * channel with destination to the primate processor block. - * When this bit is ‘0’, this flag has no effect. + * When this bit is '0', this flag has no effect. */ #define HWRM_FUNC_CFG_INPUT_MPC_CHNLS_PRIMATE_DISABLE UINT32_C(0x200) /* @@ -16045,7 +17217,23 @@ typedef struct hwrm_func_cfg_input { * ring that is assigned to a function has a valid mtu. */ uint16_t host_mtu; - uint8_t unused_0[4]; + uint32_t flags2; + /* + * If this bit is set to 1, the driver is requesting the firmware + * to see if the assets (i.e., the number of KTLS key contexts) + * requested in this command are available. The firmware will return + * an error if the requested assets are not available. The firmware + * will NOT reserve the assets if they are available. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS2_KTLS_KEY_CTX_ASSETS_TEST UINT32_C(0x1) + /* + * If this bit is set to 1, the driver is requesting the firmware + * to see if the assets (i.e., the number of QUIC key contexts) + * requested in this command are available. The firmware will return + * an error if the requested assets are not available. The firmware + * will NOT reserve the assets if they are available. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS2_QUIC_KEY_CTX_ASSETS_TEST UINT32_C(0x2) uint32_t enables2; /* * This bit must be '1' for the kdnet_mode field to be @@ -16057,10 +17245,55 @@ typedef struct hwrm_func_cfg_input { * configured. Legacy controller core FW may silently ignore * the db_page_size programming request through this command. */ - #define HWRM_FUNC_CFG_INPUT_ENABLES2_DB_PAGE_SIZE UINT32_C(0x2) + #define HWRM_FUNC_CFG_INPUT_ENABLES2_DB_PAGE_SIZE UINT32_C(0x2) + /* + * This bit must be '1' for the num_quic_tx_key_ctxs field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_QUIC_TX_KEY_CTXS UINT32_C(0x4) + /* + * This bit must be '1' for the num_quic_rx_key_ctxs field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_QUIC_RX_KEY_CTXS UINT32_C(0x8) + /* + * This bit must be '1' for the roce_max_av_per_vf field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_AV_PER_VF UINT32_C(0x10) + /* + * This bit must be '1' for the roce_max_cq_per_vf field to be + * configured. Only valid for PF. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_CQ_PER_VF UINT32_C(0x20) + /* + * This bit must be '1' for the roce_max_mrw_per_vf field to be + * configured. Only valid for PF. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_MRW_PER_VF UINT32_C(0x40) + /* + * This bit must be '1' for the roce_max_qp_per_vf field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_QP_PER_VF UINT32_C(0x80) + /* + * This bit must be '1' for the roce_max_srq_per_vf field to be + * configured. Only valid for PF. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_SRQ_PER_VF UINT32_C(0x100) + /* + * This bit must be '1' for the roce_max_gid_per_vf field to be + * configured. Only valid for PF. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_ROCE_MAX_GID_PER_VF UINT32_C(0x200) /* - * KDNet mode for the port for this function. If NPAR is - * also configured on this port, it takes precedence. KDNet + * This bit must be '1' for the xid_partition_cfg field to be + * configured. Only valid for PF. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES2_XID_PARTITION_CFG UINT32_C(0x400) + /* + * KDNet mode for the port for this function. If NPAR is + * also configured on this port, it takes precedence. KDNet * mode is ignored for a VF. */ uint8_t port_kdnet_mode; @@ -16103,11 +17336,42 @@ typedef struct hwrm_func_cfg_input { #define HWRM_FUNC_CFG_INPUT_DB_PAGE_SIZE_4MB UINT32_C(0xa) #define HWRM_FUNC_CFG_INPUT_DB_PAGE_SIZE_LAST HWRM_FUNC_CFG_INPUT_DB_PAGE_SIZE_4MB uint8_t unused_1[2]; - /* Number of Tx Key Contexts requested. */ - uint32_t num_tx_key_ctxs; - /* Number of Rx Key Contexts requested. */ - uint32_t num_rx_key_ctxs; - uint8_t unused_2[4]; + /* Number of KTLS Tx Key Contexts requested. */ + uint32_t num_ktls_tx_key_ctxs; + /* Number of KTLS Rx Key Contexts requested. */ + uint32_t num_ktls_rx_key_ctxs; + /* Number of QUIC Tx Key Contexts requested. */ + uint32_t num_quic_tx_key_ctxs; + /* Number of QUIC Rx Key Contexts requested. */ + uint32_t num_quic_rx_key_ctxs; + /* Number of AVs per VF. Only valid for PF. */ + uint32_t roce_max_av_per_vf; + /* Number of CQs per VF. Only valid for PF. */ + uint32_t roce_max_cq_per_vf; + /* Number of MR/MWs per VF. Only valid for PF. */ + uint32_t roce_max_mrw_per_vf; + /* Number of QPs per VF. Only valid for PF. */ + uint32_t roce_max_qp_per_vf; + /* Number of SRQs per VF. Only valid for PF. */ + uint32_t roce_max_srq_per_vf; + /* Number of GIDs per VF. Only valid for PF. */ + uint32_t roce_max_gid_per_vf; + /* + * Bitmap of context types that have XID partition enabled. + * Only valid for PF. + */ + uint16_t xid_partition_cfg; + /* + * When this bit is '1', it indicates that driver enables XID + * partition on Tx crypto key contexts. + */ + #define HWRM_FUNC_CFG_INPUT_XID_PARTITION_CFG_TX_CK UINT32_C(0x1) + /* + * When this bit is '1', it indicates that driver enables XID + * partition on Rx crypto key contexts. + */ + #define HWRM_FUNC_CFG_INPUT_XID_PARTITION_CFG_RX_CK UINT32_C(0x2) + uint16_t unused_2; } hwrm_func_cfg_input_t, *phwrm_func_cfg_input_t; /* hwrm_func_cfg_output (size:128b/16B) */ @@ -16124,9 +17388,9 @@ typedef struct hwrm_func_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16240,7 +17504,7 @@ typedef struct hwrm_func_qstats_output { uint64_t tx_bcast_pkts; /* * Number of transmitted packets that were discarded due to - * internal NIC resource problems. For transmit, this + * internal NIC resource problems. For transmit, this * can only happen if TMP is configured to allow dropping * in HOL blocking conditions, which is not a normal * configuration. @@ -16267,7 +17531,7 @@ typedef struct hwrm_func_qstats_output { uint64_t rx_bcast_pkts; /* * Number of received packets that were discarded on the function - * due to resource limitations. This can happen for 3 reasons. + * due to resource limitations. This can happen for 3 reasons. * # The BD used for the packet has a bad format. * # There were no BDs available in the ring for the packet. * # There were no BDs available on-chip for the packet. @@ -16298,7 +17562,7 @@ typedef struct hwrm_func_qstats_output { * cleared. Firmware starts the sequence from zero. It increments * the sequence number every time the statistics of the function * are cleared, which can be triggered by a clear statistics request - * or by freeing all statistics contexts of the function. If an user + * or by freeing all statistics contexts of the function. If a user * is interested in knowing if the statistics have been cleared * since the last query, it can keep track of this sequence number * between queries. @@ -16307,9 +17571,9 @@ typedef struct hwrm_func_qstats_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16448,9 +17712,9 @@ typedef struct hwrm_func_qstats_ext_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16515,9 +17779,9 @@ typedef struct hwrm_func_clr_stats_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16581,9 +17845,9 @@ typedef struct hwrm_func_vf_resc_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16655,14 +17919,15 @@ typedef struct hwrm_func_drv_rgtr_input { #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_16BIT_VER_MODE UINT32_C(0x4) /* * When this bit is '1', the function is indicating support of - * 64bit flow handle. The firmware that only supports 64bit flow + * 64bit flow handle. The firmware that only supports 64bit flow * handle should check this bit before allowing processing of - * HWRM_CFA_FLOW_XXX commands from the requesting function as firmware - * with 64bit flow handle support can only be compatible with drivers - * that support 64bit flow handle. The legacy drivers that don't support - * 64bit flow handle won't be able to use HWRM_CFA_FLOW_XXX commands when - * running with new firmware that only supports 64bit flow handle. The new - * firmware support 64bit flow handle returns HWRM_ERR_CODE_CMD_NOT_SUPPORTED + * HWRM_CFA_FLOW_XXX commands from the requesting function as + * firmware with 64bit flow handle support can only be compatible + * with drivers that support 64bit flow handle. The legacy drivers + * that don't support 64bit flow handle won't be able to use + * HWRM_CFA_FLOW_XXX commands when running with new firmware that + * only supports 64bit flow handle. The new firmware support 64bit + * flow handle returns HWRM_ERR_CODE_CMD_NOT_SUPPORTED * status to the legacy driver when encounters these commands. */ #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FLOW_HANDLE_64BIT_MODE UINT32_C(0x8) @@ -16690,11 +17955,12 @@ typedef struct hwrm_func_drv_rgtr_input { #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT UINT32_C(0x20) /* * When this bit is 1, the function is indicating the support of the - * Master capability. The Firmware will use this capability to select the - * Master function. The master function will be used to initiate - * designated functionality like error recovery etc… If none of the - * registered PF’s or trusted VF’s indicate this support, then - * firmware will select the 1st registered PF as Master capable instance. + * Master capability. The Firmware will use this capability to select + * the Master function. The master function will be used to initiate + * designated functionality like error recovery etc. If none of the + * registered PF's or trusted VF's indicate this support, then + * firmware will select the 1st registered PF as Master capable + * instance. */ #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_MASTER_SUPPORT UINT32_C(0x40) /* @@ -16730,6 +17996,22 @@ typedef struct hwrm_func_drv_rgtr_input { * corresponding queue configuration on the RX side */ #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ASYM_QUEUE_CFG_SUPPORT UINT32_C(0x400) + /* + * When this bit is 1, the function's driver is indicating to the + * firmware that the Ingress NIC flows will be programmed by the + * TruFlow application and the firmware flow manager should reject + * flow-create commands that programs ingress lookup flows for this + * function. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_TF_INGRESS_NIC_FLOW_MODE UINT32_C(0x800) + /* + * When this bit is 1, the function's driver is indicating to the + * firmware that the Egress NIC flows will be programmed by the + * TruFlow application and the firmware flow manager should reject + * flow-create commands that programs Egress lookup flows for this + * function. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_TF_EGRESS_NIC_FLOW_MODE UINT32_C(0x1000) uint32_t enables; /* * This bit must be '1' for the os_type field to be @@ -16756,7 +18038,10 @@ typedef struct hwrm_func_drv_rgtr_input { * configured. */ #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD UINT32_C(0x10) - /* This value indicates the type of OS. The values are based on CIM_OperatingSystem.mof file as published by the DMTF. */ + /* + * This value indicates the type of OS. The values are based on + * CIM_OperatingSystem.mof file as published by the DMTF. + */ uint16_t os_type; /* Unknown */ #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_UNKNOWN UINT32_C(0x0) @@ -16854,9 +18139,9 @@ typedef struct hwrm_func_drv_rgtr_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -16921,9 +18206,9 @@ typedef struct hwrm_func_drv_unrgtr_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17057,9 +18342,9 @@ typedef struct hwrm_func_buf_rgtr_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17129,9 +18414,9 @@ typedef struct hwrm_func_buf_unrgtr_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17181,7 +18466,17 @@ typedef struct hwrm_func_drv_qver_input { * function. */ uint16_t fid; - uint8_t unused_0[2]; + /* + * This field is used to indicate the driver type. + * L2 or RoCE + */ + uint8_t driver_type; + /* L2 driver version */ + #define HWRM_FUNC_DRV_QVER_INPUT_DRIVER_TYPE_L2 UINT32_C(0x0) + /* RoCE driver version */ + #define HWRM_FUNC_DRV_QVER_INPUT_DRIVER_TYPE_ROCE UINT32_C(0x1) + #define HWRM_FUNC_DRV_QVER_INPUT_DRIVER_TYPE_LAST HWRM_FUNC_DRV_QVER_INPUT_DRIVER_TYPE_ROCE + uint8_t unused_0; } hwrm_func_drv_qver_input_t, *phwrm_func_drv_qver_input_t; /* hwrm_func_drv_qver_output (size:256b/32B) */ @@ -17195,7 +18490,10 @@ typedef struct hwrm_func_drv_qver_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* This value indicates the type of OS. The values are based on CIM_OperatingSystem.mof file as published by the DMTF. */ + /* + * This value indicates the type of OS. The values are based on + * CIM_OperatingSystem.mof file as published by the DMTF. + */ uint16_t os_type; /* Unknown */ #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_UNKNOWN UINT32_C(0x0) @@ -17238,9 +18536,9 @@ typedef struct hwrm_func_drv_qver_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17291,7 +18589,7 @@ typedef struct hwrm_func_resource_qcaps_input { uint8_t unused_0[6]; } hwrm_func_resource_qcaps_input_t, *phwrm_func_resource_qcaps_input_t; -/* hwrm_func_resource_qcaps_output (size:576b/72B) */ +/* hwrm_func_resource_qcaps_output (size:704b/88B) */ typedef struct hwrm_func_resource_qcaps_output { /* The specific error status for the command. */ @@ -17302,13 +18600,22 @@ typedef struct hwrm_func_resource_qcaps_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Maximum guaranteed number of VFs supported by PF. Not applicable for VFs. */ + /* + * Maximum guaranteed number of VFs supported by PF. Not applicable for + * VFs. + */ uint16_t max_vfs; - /* Maximum guaranteed number of MSI-X vectors supported by function */ + /* Maximum guaranteed number of MSI-X vectors supported by function. */ uint16_t max_msix; - /* Hint of strategy to be used by PF driver to reserve resources for its VF */ + /* + * Hint of strategy to be used by PF driver to reserve resources for + * its VF. + */ uint16_t vf_reservation_strategy; - /* The PF driver should evenly divide its remaining resources among all VFs. */ + /* + * The PF driver should evenly divide its remaining resources among + * all VFs. + */ #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MAXIMAL UINT32_C(0x0) /* The PF driver should only reserve minimal resources for each VF. */ #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MINIMAL UINT32_C(0x1) @@ -17318,7 +18625,7 @@ typedef struct hwrm_func_resource_qcaps_output { */ #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MINIMAL_STATIC UINT32_C(0x2) #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_LAST HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MINIMAL_STATIC - /* Minimum guaranteed number of RSS/COS contexts */ + /* Minimum guaranteed number of RSS/COS contexts. */ uint16_t min_rsscos_ctx; /* Maximum non-guaranteed number of RSS/COS contexts */ uint16_t max_rsscos_ctx; @@ -17351,32 +18658,42 @@ typedef struct hwrm_func_resource_qcaps_output { /* Maximum non-guaranteed number of ring groups */ uint16_t max_hw_ring_grps; /* - * Maximum number of inputs into the transmit scheduler for this function. - * The number of TX rings assigned to the function cannot exceed this value. + * Maximum number of inputs into the transmit scheduler for this + * function. The number of TX rings assigned to the function cannot + * exceed this value. */ uint16_t max_tx_scheduler_inputs; uint16_t flags; /* * When this bit is '1', it indicates that VF_RESOURCE_CFG supports - * feature to reserve all minimum resources when minimum >= 1, otherwise - * returns an error. + * feature to reserve all minimum resources when minimum >= 1, + * otherwise returns an error. */ #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_FLAGS_MIN_GUARANTEED UINT32_C(0x1) - uint8_t unused_0[2]; - /* Minimum guaranteed number of Tx Key Contexts */ - uint32_t min_tx_key_ctxs; - /* Maximum non-guaranteed number of Tx Key Contexts */ - uint32_t max_tx_key_ctxs; - /* Minimum guaranteed number of Rx Key Contexts */ - uint32_t min_rx_key_ctxs; - /* Maximum non-guaranteed number of Rx Key Contexts */ - uint32_t max_rx_key_ctxs; - uint8_t unused_1[3]; + /* Minimum guaranteed number of MSI-X vectors supported by function */ + uint16_t min_msix; + /* Minimum guaranteed number of KTLS Tx Key Contexts */ + uint32_t min_ktls_tx_key_ctxs; + /* Maximum non-guaranteed number of KTLS Tx Key Contexts */ + uint32_t max_ktls_tx_key_ctxs; + /* Minimum guaranteed number of KTLS Rx Key Contexts */ + uint32_t min_ktls_rx_key_ctxs; + /* Maximum non-guaranteed number of KTLS Rx Key Contexts */ + uint32_t max_ktls_rx_key_ctxs; + /* Minimum guaranteed number of QUIC Tx Key Contexts */ + uint32_t min_quic_tx_key_ctxs; + /* Maximum non-guaranteed number of QUIC Tx Key Contexts */ + uint32_t max_quic_tx_key_ctxs; + /* Minimum guaranteed number of QUIC Rx Key Contexts */ + uint32_t min_quic_rx_key_ctxs; + /* Maximum non-guaranteed number of QUIC Rx Key Contexts */ + uint32_t max_quic_rx_key_ctxs; + uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17387,7 +18704,7 @@ typedef struct hwrm_func_resource_qcaps_output { *****************************/ -/* hwrm_func_vf_resource_cfg_input (size:576b/72B) */ +/* hwrm_func_vf_resource_cfg_input (size:704b/88B) */ typedef struct hwrm_func_vf_resource_cfg_input { /* The HWRM command request type. */ @@ -17461,18 +18778,27 @@ typedef struct hwrm_func_vf_resource_cfg_input { * error, keep all existing reservations before the call. */ #define HWRM_FUNC_VF_RESOURCE_CFG_INPUT_FLAGS_MIN_GUARANTEED UINT32_C(0x1) - uint8_t unused_0[2]; - /* Minimum guaranteed number of Tx Key Contexts */ - uint32_t min_tx_key_ctxs; - /* Maximum non-guaranteed number of Tx Key Contexts */ - uint32_t max_tx_key_ctxs; - /* Minimum guaranteed number of Rx Key Contexts */ - uint32_t min_rx_key_ctxs; - /* Maximum non-guaranteed number of Rx Key Contexts */ - uint32_t max_rx_key_ctxs; + /* Minimum guaranteed number of MSI-X vectors for the function */ + uint16_t min_msix; + /* Minimum guaranteed number of KTLS Tx Key Contexts */ + uint32_t min_ktls_tx_key_ctxs; + /* Maximum non-guaranteed number of KTLS Tx Key Contexts */ + uint32_t max_ktls_tx_key_ctxs; + /* Minimum guaranteed number of KTLS Rx Key Contexts */ + uint32_t min_ktls_rx_key_ctxs; + /* Maximum non-guaranteed number of KTLS Rx Key Contexts */ + uint32_t max_ktls_rx_key_ctxs; + /* Minimum guaranteed number of QUIC Tx Key Contexts */ + uint32_t min_quic_tx_key_ctxs; + /* Maximum non-guaranteed number of QUIC Tx Key Contexts */ + uint32_t max_quic_tx_key_ctxs; + /* Minimum guaranteed number of QUIC Rx Key Contexts */ + uint32_t min_quic_rx_key_ctxs; + /* Maximum non-guaranteed number of QUIC Rx Key Contexts */ + uint32_t max_quic_rx_key_ctxs; } hwrm_func_vf_resource_cfg_input_t, *phwrm_func_vf_resource_cfg_input_t; -/* hwrm_func_vf_resource_cfg_output (size:320b/40B) */ +/* hwrm_func_vf_resource_cfg_output (size:384b/48B) */ typedef struct hwrm_func_vf_resource_cfg_output { /* The specific error status for the command. */ @@ -17499,16 +18825,20 @@ typedef struct hwrm_func_vf_resource_cfg_output { uint16_t reserved_stat_ctx; /* Reserved number of ring groups */ uint16_t reserved_hw_ring_grps; - /* Actual number of Tx Key Contexts reserved */ - uint32_t reserved_tx_key_ctxs; - /* Actual number of Rx Key Contexts reserved */ - uint32_t reserved_rx_key_ctxs; + /* Actual number of KTLS Tx Key Contexts reserved */ + uint32_t reserved_ktls_tx_key_ctxs; + /* Actual number of KTLS Rx Key Contexts reserved */ + uint32_t reserved_ktls_rx_key_ctxs; + /* Actual number of QUIC Tx Key Contexts reserved */ + uint32_t reserved_quic_tx_key_ctxs; + /* Actual number of QUIC Rx Key Contexts reserved */ + uint32_t reserved_quic_rx_key_ctxs; uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17592,11 +18922,17 @@ typedef struct hwrm_func_backing_store_qcaps_output { uint16_t cq_entry_size; /* Maximum number of VNIC context entries supported for this function. */ uint16_t vnic_max_vnic_entries; - /* Maximum number of Ring table context entries supported for this function. */ + /* + * Maximum number of Ring table context entries supported for this + * function. + */ uint16_t vnic_max_ring_table_entries; /* Number of bytes that must be allocated for each context entry. */ uint16_t vnic_entry_size; - /* Maximum number of statistic context entries supported for this function. */ + /* + * Maximum number of statistic context entries supported for this + * function. + */ uint32_t stat_max_entries; /* Number of bytes that must be allocated for each context entry. */ uint16_t stat_entry_size; @@ -17618,7 +18954,8 @@ typedef struct hwrm_func_backing_store_qcaps_output { * num_entries = num_vnics + num_l2_tx_rings + 2 * num_roce_qps + tqm_min_size * * Where: - * num_vnics is the number of VNICs allocated in the VNIC backing store + * num_vnics is the number of VNICs allocated in the VNIC backing + * store * num_l2_tx_rings is the number of L2 rings in the QP backing store * num_roce_qps is the number of RoCE QPs in the QP backing store * tqm_min_size is tqm_min_entries_per_ring reported by @@ -17783,13 +19120,18 @@ typedef struct hwrm_func_backing_store_qcaps_output { * function. */ uint32_t rkc_max_entries; + /* + * Additional number of RoCE QP context entries required for this + * function to support fast QP destroy feature. + */ + uint16_t fast_qpmd_qp_num_entries; /* Reserved for future. */ - uint8_t rsvd1[7]; + uint8_t rsvd1[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -17905,12 +19247,12 @@ typedef struct hwrm_func_backing_store_cfg_input { * This bit must be '1' for the vnic fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC UINT32_C(0x8) + #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC UINT32_C(0x8) /* * This bit must be '1' for the stat fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT UINT32_C(0x10) + #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT UINT32_C(0x10) /* * This bit must be '1' for the tqm_sp fields to be * configured. @@ -17960,7 +19302,7 @@ typedef struct hwrm_func_backing_store_cfg_input { * This bit must be '1' for the mrav fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV UINT32_C(0x4000) + #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV UINT32_C(0x4000) /* * This bit must be '1' for the tim fields to be * configured. @@ -17991,6 +19333,11 @@ typedef struct hwrm_func_backing_store_cfg_input { * fields to be configured. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_RKC UINT32_C(0x100000) + /* + * This bit must be '1' for the number of QPs reserved for fast + * qp modify destroy feature to be configured. + */ + #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP_FAST_QPMD UINT32_C(0x200000) /* QPC page size and level. */ uint8_t qpc_pg_size_qpc_lvl; /* QPC PBL indirect levels. */ @@ -18000,7 +19347,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2 /* QPC page size. */ @@ -18028,7 +19378,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_SRQ_LVL_LVL_2 /* SRQ page size. */ @@ -18056,7 +19409,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_CQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_CQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_CQ_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_CQ_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_CQ_LVL_LVL_2 /* CQ page size. */ @@ -18084,7 +19440,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_VNIC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_VNIC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_VNIC_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_VNIC_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_VNIC_LVL_LVL_2 /* VNIC page size. */ @@ -18112,7 +19471,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_STAT_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_STAT_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_STAT_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_STAT_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_STAT_LVL_LVL_2 /* Stat page size. */ @@ -18140,7 +19502,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_SP_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_SP_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_SP_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_SP_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_SP_LVL_LVL_2 /* TQM slow path page size. */ @@ -18168,7 +19533,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING0_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING0_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING0_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING0_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING0_LVL_LVL_2 /* TQM ring 0 page size. */ @@ -18196,7 +19564,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING1_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING1_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING1_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING1_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING1_LVL_LVL_2 /* TQM ring 1 page size. */ @@ -18224,7 +19595,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING2_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING2_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING2_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING2_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING2_LVL_LVL_2 /* TQM ring 2 page size. */ @@ -18252,7 +19626,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING3_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING3_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING3_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING3_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING3_LVL_LVL_2 /* TQM ring 3 page size. */ @@ -18280,7 +19657,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING4_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING4_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING4_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING4_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING4_LVL_LVL_2 /* TQM ring 4 page size. */ @@ -18308,7 +19688,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING5_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING5_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING5_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING5_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING5_LVL_LVL_2 /* TQM ring 5 page size. */ @@ -18336,7 +19719,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING6_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING6_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING6_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING6_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING6_LVL_LVL_2 /* TQM ring 6 page size. */ @@ -18364,7 +19750,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING7_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING7_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING7_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING7_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TQM_RING7_LVL_LVL_2 /* TQM ring 7 page size. */ @@ -18392,7 +19781,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_MRAV_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_MRAV_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_MRAV_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_MRAV_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_MRAV_LVL_LVL_2 /* MR/AV page size. */ @@ -18420,7 +19812,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TIM_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TIM_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TIM_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TIM_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TIM_LVL_LVL_2 /* Timer page size. */ @@ -18487,11 +19882,11 @@ typedef struct hwrm_func_backing_store_cfg_input { * num_entries = num_vnics + num_l2_tx_rings + 2 * num_roce_qps + tqm_min_size * * Where: - * num_vnics is the number of VNICs allocated in the VNIC backing store - * num_l2_tx_rings is the number of L2 rings in the QP backing store - * num_roce_qps is the number of RoCE QPs in the QP backing store - * tqm_min_size is tqm_min_entries_per_ring reported by - * HWRM_FUNC_BACKING_STORE_QCAPS + * num_vnics is the number of VNICs allocated in the VNIC backing + * store num_l2_tx_rings is the number of L2 rings in the QP backing + * store num_roce_qps is the number of RoCE QPs in the QP backing + * store tqm_min_size is tqm_min_entries_per_ring reported by + * HWRM_FUNC_BACKING_STORE_QCAPS * * Note that TQM ring sizes cannot be extended while the system is * operational. If a PF driver needs to extend a TQM ring, it needs @@ -18777,7 +20172,10 @@ typedef struct hwrm_func_backing_store_cfg_input { #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TKC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TKC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TKC_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_TKC_LVL_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_TKC_LVL_LVL_2 /* Tx KTLS context page size. */ @@ -18827,8 +20225,11 @@ typedef struct hwrm_func_backing_store_cfg_input { /* 1GB. */ #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_RKC_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_RKC_PG_SIZE_LAST HWRM_FUNC_BACKING_STORE_CFG_INPUT_RKC_PG_SIZE_PG_1G - /* Reserved for future. */ - uint8_t rsvd[2]; + /* + * Number of RoCE QP context entries reserved for this + * function to support fast QP modify destroy feature. + */ + uint16_t qp_num_fast_qpmd_entries; } hwrm_func_backing_store_cfg_input_t, *phwrm_func_backing_store_cfg_input_t; /* hwrm_func_backing_store_cfg_output (size:128b/16B) */ @@ -18845,9 +20246,9 @@ typedef struct hwrm_func_backing_store_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -18935,12 +20336,12 @@ typedef struct hwrm_func_backing_store_qcfg_output { * This bit must be '1' for the vnic fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_VNIC UINT32_C(0x8) + #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_VNIC UINT32_C(0x8) /* * This bit must be '1' for the stat fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_STAT UINT32_C(0x10) + #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_STAT UINT32_C(0x10) /* * This bit must be '1' for the tqm_sp fields to be * configured. @@ -18990,7 +20391,7 @@ typedef struct hwrm_func_backing_store_qcfg_output { * This bit must be '1' for the mrav fields to be * configured. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_MRAV UINT32_C(0x4000) + #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_MRAV UINT32_C(0x4000) /* * This bit must be '1' for the tim fields to be * configured. @@ -19021,6 +20422,11 @@ typedef struct hwrm_func_backing_store_qcfg_output { * fields to be configured. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_RKC UINT32_C(0x100000) + /* + * This bit must be '1' for the number of QPs reserved for fast + * qp modify destroy feature to be configured. + */ + #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_ENABLES_QP_FAST_QPMD UINT32_C(0x200000) /* QPC page size and level. */ uint8_t qpc_pg_size_qpc_lvl; /* QPC PBL indirect levels. */ @@ -19030,7 +20436,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_QPC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_QPC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_QPC_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_QPC_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_QPC_LVL_LVL_2 /* QPC page size. */ @@ -19058,7 +20467,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_SRQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_SRQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_SRQ_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_SRQ_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_SRQ_LVL_LVL_2 /* SRQ page size. */ @@ -19086,7 +20498,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_CQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_CQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_CQ_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_CQ_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_CQ_LVL_LVL_2 /* CQ page size. */ @@ -19114,7 +20529,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_VNIC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_VNIC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_VNIC_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_VNIC_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_VNIC_LVL_LVL_2 /* VNIC page size. */ @@ -19142,7 +20560,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_STAT_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_STAT_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_STAT_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_STAT_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_STAT_LVL_LVL_2 /* Stat page size. */ @@ -19170,7 +20591,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_SP_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_SP_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_SP_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_SP_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_SP_LVL_LVL_2 /* TQM slow path page size. */ @@ -19198,7 +20622,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING0_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING0_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING0_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING0_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING0_LVL_LVL_2 /* TQM ring 0 page size. */ @@ -19226,7 +20653,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING1_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING1_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING1_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING1_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING1_LVL_LVL_2 /* TQM ring 1 page size. */ @@ -19254,7 +20684,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING2_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING2_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING2_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING2_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING2_LVL_LVL_2 /* TQM ring 2 page size. */ @@ -19282,7 +20715,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING3_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING3_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING3_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING3_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING3_LVL_LVL_2 /* TQM ring 3 page size. */ @@ -19310,7 +20746,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING4_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING4_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING4_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING4_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING4_LVL_LVL_2 /* TQM ring 4 page size. */ @@ -19338,7 +20777,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING5_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING5_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING5_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING5_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING5_LVL_LVL_2 /* TQM ring 5 page size. */ @@ -19366,7 +20808,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING6_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING6_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING6_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING6_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING6_LVL_LVL_2 /* TQM ring 6 page size. */ @@ -19394,7 +20839,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING7_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING7_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING7_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING7_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TQM_RING7_LVL_LVL_2 /* TQM ring 7 page size. */ @@ -19422,7 +20870,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_MRAV_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_MRAV_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_MRAV_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_MRAV_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_MRAV_LVL_LVL_2 /* MR/AV page size. */ @@ -19450,7 +20901,10 @@ typedef struct hwrm_func_backing_store_qcfg_output { #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TIM_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TIM_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TIM_LVL_LVL_2 UINT32_C(0x2) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TIM_LVL_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_TIM_LVL_LVL_2 /* Timer page size. */ @@ -19734,10 +21188,15 @@ typedef struct hwrm_func_backing_store_qcfg_output { /* 1GB. */ #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_RKC_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) #define HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_RKC_PG_SIZE_LAST HWRM_FUNC_BACKING_STORE_QCFG_OUTPUT_RKC_PG_SIZE_PG_1G - uint8_t unused_1[5]; + /* + * Number of RoCE QP context entries required for this + * function to support fast QP modify destroy feature. + */ + uint16_t qp_num_fast_qpmd_entries; + uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as 1 + * is completely written to RAM. This field should be read as 1 * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field @@ -20101,7 +21560,7 @@ typedef struct hwrm_error_recovery_qcfg_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field @@ -20164,9 +21623,9 @@ typedef struct hwrm_func_echo_response_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -20312,9 +21771,9 @@ typedef struct hwrm_func_ptp_pin_qcfg_output { uint8_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -20502,9 +21961,9 @@ typedef struct hwrm_func_ptp_pin_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -20632,7 +22091,9 @@ typedef struct hwrm_func_ptp_cfg_input { #define HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_8K UINT32_C(0x2) /* 10Mhz sync in frequency. */ #define HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_10M UINT32_C(0x3) - #define HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_LAST HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_10M + /* 25Mhz sync in frequency. */ + #define HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_25M UINT32_C(0x4) + #define HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_LAST HWRM_FUNC_PTP_CFG_INPUT_PTP_FREQ_ADJ_DLL_PHASE_25M uint8_t unused_0[3]; /* * Period in nanoseconds (ns) for external signal @@ -20684,9 +22145,9 @@ typedef struct hwrm_func_ptp_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -20771,9 +22232,9 @@ typedef struct hwrm_func_ptp_ts_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -20915,9 +22376,9 @@ typedef struct hwrm_func_ptp_ext_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -21012,20 +22473,229 @@ typedef struct hwrm_func_ptp_ext_qcfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; } hwrm_func_ptp_ext_qcfg_output_t, *phwrm_func_ptp_ext_qcfg_output_t; +/************************************* + * hwrm_func_timedtx_pacing_rate_add * + *************************************/ + + +/* hwrm_func_timedtx_pacing_rate_add_input (size:192b/24B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_add_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * This field indicates TimedTx pacing rate in kbps. + * The driver needs to add the rate into the hardware rate table + * before requesting the pacing rate for a flow in TimedTX BD and + * this addition should be done for each function rather than for + * each flow/QP within the function. + */ + uint32_t rate; + uint8_t unused_0[4]; +} hwrm_func_timedtx_pacing_rate_add_input_t, *phwrm_func_timedtx_pacing_rate_add_input_t; + +/* hwrm_func_timedtx_pacing_rate_add_output (size:128b/16B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_add_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This field indicates the logical rate ID that is assigned to the + * rate in the rate table. The driver should use this ID for future + * reference to this rate. + */ + uint16_t rate_id; + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_timedtx_pacing_rate_add_output_t, *phwrm_func_timedtx_pacing_rate_add_output_t; + +/**************************************** + * hwrm_func_timedtx_pacing_rate_delete * + ****************************************/ + + +/* hwrm_func_timedtx_pacing_rate_delete_input (size:192b/24B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_delete_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * The logical rate ID that is returned in the TimedTX pacing rate + * add operation. + */ + uint16_t rate_id; + uint8_t unused_0[6]; +} hwrm_func_timedtx_pacing_rate_delete_input_t, *phwrm_func_timedtx_pacing_rate_delete_input_t; + +/* hwrm_func_timedtx_pacing_rate_delete_output (size:128b/16B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_delete_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_timedtx_pacing_rate_delete_output_t, *phwrm_func_timedtx_pacing_rate_delete_output_t; + +/*************************************** + * hwrm_func_timedtx_pacing_rate_query * + ***************************************/ + + +/* hwrm_func_timedtx_pacing_rate_query_input (size:192b/24B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_query_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint8_t unused_0[8]; +} hwrm_func_timedtx_pacing_rate_query_input_t, *phwrm_func_timedtx_pacing_rate_query_input_t; + +/* hwrm_func_timedtx_pacing_rate_query_output (size:4224b/528B) */ + +typedef struct hwrm_func_timedtx_pacing_rate_query_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This field indicates the rates that the function has added into + * the hardware rate table. This is an array of 128 entries. Starting + * with index 0, registered rates are populated in the initial entries + * of the array, remaining entries are filled up with 0. + */ + uint32_t rates[128]; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_timedtx_pacing_rate_query_output_t, *phwrm_func_timedtx_pacing_rate_query_output_t; + /*************************** * hwrm_func_key_ctx_alloc * ***************************/ -/* hwrm_func_key_ctx_alloc_input (size:320b/40B) */ +/* hwrm_func_key_ctx_alloc_input (size:384b/48B) */ typedef struct hwrm_func_key_ctx_alloc_input { /* The HWRM command request type. */ @@ -21058,9 +22728,26 @@ typedef struct hwrm_func_key_ctx_alloc_input { uint64_t resp_addr; /* Function ID. */ uint16_t fid; - /* Number of Key Contexts to be allocated. */ + /* + * Number of Key Contexts to be allocated. + * When running in the XID partition mode, if the call is made by + * a VF driver, this field specifies the number of XIDs requested + * by the VF driver. The XID partitions are managed by the PF + * driver in XID partition mode and the VF command will be + * redirected to the PF driver. The PF driver may reduce this + * number if it cannot allocate a big enough block of XID + * partitions to satisfy the request. + * This field must not exceed the maximum batch size specified in + * the max_key_ctxs_alloc field of the HWRM_FUNC_QCAPS response, + * must not be zero, and must be integer multiples of the + * partition size specified in the ctxs_per_partition field of + * the HWRM_FUNC_QCAPS response. + */ uint16_t num_key_ctxs; - /* DMA buffer size in bytes. */ + /* + * DMA buffer size in bytes. This field in invalid in the XID + * partition mode. + */ uint32_t dma_bufr_size_bytes; /* Key Context type. */ uint8_t key_ctx_type; @@ -21074,11 +22761,24 @@ typedef struct hwrm_func_key_ctx_alloc_input { #define HWRM_FUNC_KEY_CTX_ALLOC_INPUT_KEY_CTX_TYPE_QUIC_RX UINT32_C(0x3) #define HWRM_FUNC_KEY_CTX_ALLOC_INPUT_KEY_CTX_TYPE_LAST HWRM_FUNC_KEY_CTX_ALLOC_INPUT_KEY_CTX_TYPE_QUIC_RX uint8_t unused_0[7]; - /* Host DMA address to send back KTLS context IDs. */ + /* + * Host DMA address to send back KTLS context IDs. This field is + * invalid in the XID partition mode. + */ uint64_t host_dma_addr; + /* + * This field is only used by the PF driver that manages the XID + * partitions. This field specifies the starting XID of one or + * more contiguous XID partitions allocated by the PF driver. + * This field is not used by the VF driver. + * If the call is successful, this starting XID value will be + * returned in the partition_start_xid field of the response. + */ + uint32_t partition_start_xid; + uint8_t unused_1[4]; } hwrm_func_key_ctx_alloc_input_t, *phwrm_func_key_ctx_alloc_input_t; -/* hwrm_func_key_ctx_alloc_output (size:128b/16B) */ +/* hwrm_func_key_ctx_alloc_output (size:192b/24B) */ typedef struct hwrm_func_key_ctx_alloc_output { /* The specific error status for the command. */ @@ -21089,7 +22789,7 @@ typedef struct hwrm_func_key_ctx_alloc_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Actual number of Key Contexts allocated. */ + /* Number of Key Contexts that have been allocated. */ uint16_t num_key_ctxs_allocated; /* Control flags. */ uint8_t flags; @@ -21097,21 +22797,116 @@ typedef struct hwrm_func_key_ctx_alloc_output { * When set, it indicates that all key contexts allocated by this * command are contiguous. As a result, the driver has to read the * start context ID from the first entry of the DMA data buffer - * and figures out the end context ID by “start context ID + - * num_key_ctxs_allocated - 1”. + * and figures out the end context ID by 'start context ID + + * num_key_ctxs_allocated - 1'. In XID partition mode, + * this bit should always be set. */ #define HWRM_FUNC_KEY_CTX_ALLOC_OUTPUT_FLAGS_KEY_CTXS_CONTIGUOUS UINT32_C(0x1) - uint8_t unused_0[4]; + uint8_t unused_0; + /* + * This field is only valid in the XID partition mode. It indicates + * the starting XID that has been allocated. + */ + uint32_t partition_start_xid; + uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; } hwrm_func_key_ctx_alloc_output_t, *phwrm_func_key_ctx_alloc_output_t; +/************************** + * hwrm_func_key_ctx_free * + **************************/ + + +/* hwrm_func_key_ctx_free_input (size:256b/32B) */ + +typedef struct hwrm_func_key_ctx_free_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Function ID. */ + uint16_t fid; + /* Key Context type. */ + uint8_t key_ctx_type; + /* KTLS Tx Key Context type. */ + #define HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_TX UINT32_C(0x0) + /* KTLS Rx Key Context type. */ + #define HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_RX UINT32_C(0x1) + /* QUIC Tx Key Context type. */ + #define HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_QUIC_TX UINT32_C(0x2) + /* QUIC Rx Key Context type. */ + #define HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_QUIC_RX UINT32_C(0x3) + #define HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_LAST HWRM_FUNC_KEY_CTX_FREE_INPUT_KEY_CTX_TYPE_QUIC_RX + uint8_t unused_0; + /* Starting XID of the partition that needs to be freed. */ + uint32_t partition_start_xid; + /* + * Number of entries to be freed. + * When running in the XID partition mode, this field is only + * used by the PF driver that manages the XID partitions. + * The PF driver specifies the number of XIDs to be freed and + * this number is always equal to the number of XIDs previously + * allocated successfully using HWRM_FUNC_KEY_CTX_ALLOC. + * This field is not used by the VF driver. + */ + uint16_t num_entries; + uint8_t unused_1[6]; +} hwrm_func_key_ctx_free_input_t, *phwrm_func_key_ctx_free_input_t; + +/* hwrm_func_key_ctx_free_output (size:128b/16B) */ + +typedef struct hwrm_func_key_ctx_free_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t rsvd0[7]; + /* + * This field is used in Output records to indicate that the + * output is completely written to RAM. This field should be + * read as '1' to indicate that the output has been completely + * written. When writing a command completion or response to + * an internal processor, the order of writes has to be such + * that this field is written last. + */ + uint8_t valid; +} hwrm_func_key_ctx_free_output_t, *phwrm_func_key_ctx_free_output_t; + /********************************** * hwrm_func_backing_store_cfg_v2 * **********************************/ @@ -21153,49 +22948,79 @@ typedef struct hwrm_func_backing_store_cfg_v2_input { /* Queue pair. */ #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QP UINT32_C(0x0) /* Shared receive queue. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ UINT32_C(0x1) /* Completion queue. */ #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CQ UINT32_C(0x2) /* Virtual NIC. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_VNIC UINT32_C(0x3) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_VNIC UINT32_C(0x3) /* Statistic context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_STAT UINT32_C(0x4) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_STAT UINT32_C(0x4) /* Slow-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) /* Fast-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) /* Memory Region and Memory Address Vector Context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MRAV UINT32_C(0xe) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MRAV UINT32_C(0xe) /* TIM. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TIM UINT32_C(0xf) - /* Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TKC UINT32_C(0x13) - /* Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RKC UINT32_C(0x14) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TIM UINT32_C(0xf) + /* Tx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TX_CK UINT32_C(0x13) + /* Rx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RX_CK UINT32_C(0x14) /* Mid-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) /* SQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) /* RQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) /* SRQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) /* CQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) - /* QUIC Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QUIC_TKC UINT32_C(0x1a) - /* QUIC Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QUIC_RKC UINT32_C(0x1b) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) + /* CFA table scope context. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TBL_SCOPE UINT32_C(0x1c) + /* XID partition context. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_XID_PARTITION UINT32_C(0x1d) + /* SRT trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRT_TRACE UINT32_C(0x1e) + /* SRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRT2_TRACE UINT32_C(0x1f) + /* CRT trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CRT_TRACE UINT32_C(0x20) + /* CRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CRT2_TRACE UINT32_C(0x21) + /* RIGP0 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RIGP0_TRACE UINT32_C(0x22) + /* L2 HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x23) + /* RoCE HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x24) + /* TimedTx pacing TQM ring. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TTX_PACING_TQM_RING UINT32_C(0x25) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CA0_TRACE UINT32_C(0x26) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CA1_TRACE UINT32_C(0x27) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CA2_TRACE UINT32_C(0x28) + /* RIGP1 trace. */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RIGP1_TRACE UINT32_C(0x29) /* Invalid type. */ - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) - #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_INVALID + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_INVALID /* * Instance of the backing store type. It is zero-based, * which means "0" indicates the first instance. For backing * stores with single instance only, leave this field to 0. * 1. If the backing store type is MPC TQM ring, use the following - * instance value to MPC client mapping: + * instance value to map to MPC clients: * TCE (0), RCE (1), TE_CFA(2), RE_CFA (3), PRIMATE(4) + * 2. If the backing store type is TBL_SCOPE, use the following + * instance value to map to table scope regions: + * RE_CFA_LKUP (0), RE_CFA_ACT (1), TE_CFA_LKUP(2), TE_CFA_ACT (3) + * 3. If the backing store type is XID partition, use the following + * instance value to map to context types: + * TX_CK (0), RX_CK (1) */ uint16_t instance; /* Control flags. */ @@ -21222,10 +23047,10 @@ typedef struct hwrm_func_backing_store_cfg_v2_input { * The size specified in the command will be the new size to be * configured. The operation is only valid when the specific backing * store has been configured before. Otherwise, the firmware will - * return an error. The driver needs to zero out the “entry_size”, - * “flags”, “page_dir”, and “page_size_pbl_level” fields, and the + * return an error. The driver needs to zero out the 'entry_size', + * 'flags', 'page_dir', and 'page_size_pbl_level' fields, and the * firmware will ignore these inputs. Further, the firmware expects - * the “num_entries” and any valid split entries to be no less than + * the 'num_entries' and any valid split entries to be no less than * the initial value that has been configured. If not, it will * return an error code. */ @@ -21290,7 +23115,9 @@ typedef struct hwrm_func_backing_store_cfg_v2_input { * | SRQ | srq_split_entries | * | CQ | cq_split_entries | * | VINC | vnic_split_entries | - * | MRAV | marv_split_entries | + * | MRAV | mrav_split_entries | + * | TS | ts_split_entries | + * | CK | ck_split_entries | */ uint32_t split_entry_0; /* Split entry #1. */ @@ -21299,6 +23126,20 @@ typedef struct hwrm_func_backing_store_cfg_v2_input { uint32_t split_entry_2; /* Split entry #3. */ uint32_t split_entry_3; + uint32_t enables; + /* + * This bit must be '1' for the next_bs_offset field to be + * configured. + */ + #define HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_ENABLES_NEXT_BS_OFFSET UINT32_C(0x1) + /* + * This field specifies the next byte offset of the backing store + * for the firmware to use. The driver can use this field to + * direct the firmware to resume the logging-to-host from + * the host buffer where the firmware was lastly written + * before it restarts, e.g. due to an error recovery. + */ + uint32_t next_bs_offset; } hwrm_func_backing_store_cfg_v2_input_t, *phwrm_func_backing_store_cfg_v2_input_t; /* hwrm_func_backing_store_cfg_v2_output (size:128b/16B) */ @@ -21315,7 +23156,7 @@ typedef struct hwrm_func_backing_store_cfg_v2_output { uint8_t rsvd0[7]; /* * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be + * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been completely * written. When writing a command completion or response to * an internal processor, the order of writes has to be such @@ -21365,46 +23206,79 @@ typedef struct hwrm_func_backing_store_qcfg_v2_input { /* Queue pair. */ #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_QP UINT32_C(0x0) /* Shared receive queue. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRQ UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRQ UINT32_C(0x1) /* Completion queue. */ #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CQ UINT32_C(0x2) /* Virtual NIC. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_VNIC UINT32_C(0x3) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_VNIC UINT32_C(0x3) /* Statistic context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_STAT UINT32_C(0x4) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_STAT UINT32_C(0x4) /* Slow-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) /* Fast-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) /* Memory Region and Memory Address Vector Context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_MRAV UINT32_C(0xe) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_MRAV UINT32_C(0xe) /* TIM. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TIM UINT32_C(0xf) - /* Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TKC UINT32_C(0x13) - /* Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RKC UINT32_C(0x14) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TIM UINT32_C(0xf) + /* Tx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TX_CK UINT32_C(0x13) + /* Rx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RX_CK UINT32_C(0x14) /* Mid-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) /* SQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) /* RQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) /* SRQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) /* CQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) - /* QUIC Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_QUIC_TKC UINT32_C(0x1a) - /* QUIC Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_QUIC_RKC UINT32_C(0x1b) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) + /* CFA table scope context. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TBL_SCOPE UINT32_C(0x1c) + /* VF XID partition in-use table. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_XID_PARTITION_TABLE UINT32_C(0x1d) + /* SRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRT_TRACE UINT32_C(0x1e) + /* SRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_SRT2_TRACE UINT32_C(0x1f) + /* CRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CRT_TRACE UINT32_C(0x20) + /* CRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CRT2_TRACE UINT32_C(0x21) + /* RIGP0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RIGP0_TRACE UINT32_C(0x22) + /* L2 HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x23) + /* RoCE HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x24) + /* TimedTx pacing TQM ring. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_TTX_PACING_TQM_RING UINT32_C(0x25) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CA0_TRACE UINT32_C(0x26) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CA1_TRACE UINT32_C(0x27) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_CA2_TRACE UINT32_C(0x28) + /* RIGP1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_RIGP1_TRACE UINT32_C(0x29) /* Invalid type. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_INVALID + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCFG_V2_INPUT_TYPE_INVALID /* * Instance of the backing store type. It is zero-based, * which means "0" indicates the first instance. For backing * stores with single instance only, leave this field to 0. + * 1. If the backing store type is MPC TQM ring, use the following + * instance value to map to MPC clients: + * TCE (0), RCE (1), TE_CFA(2), RE_CFA (3), PRIMATE(4) + * 2. If the backing store type is TBL_SCOPE, use the following + * instance value to map to table scope regions: + * RE_CFA_LKUP (0), RE_CFA_ACT (1), TE_CFA_LKUP(2), TE_CFA_ACT (3) + * 3. If the backing store type is XID partition, use the following + * instance value to map to context types: + * TX_CK (0), RX_CK (1) */ uint16_t instance; uint8_t rsvd[4]; @@ -21424,40 +23298,73 @@ typedef struct hwrm_func_backing_store_qcfg_v2_output { /* Type of backing store to be configured. */ uint16_t type; /* Queue pair. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_QP UINT32_C(0x0) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_QP UINT32_C(0x0) /* Shared receive queue. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRQ UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRQ UINT32_C(0x1) /* Completion queue. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CQ UINT32_C(0x2) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CQ UINT32_C(0x2) /* Virtual NIC. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_VNIC UINT32_C(0x3) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_VNIC UINT32_C(0x3) /* Statistic context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_STAT UINT32_C(0x4) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_STAT UINT32_C(0x4) /* Slow-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SP_TQM_RING UINT32_C(0x5) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SP_TQM_RING UINT32_C(0x5) /* Fast-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_FP_TQM_RING UINT32_C(0x6) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_FP_TQM_RING UINT32_C(0x6) /* Memory Region and Memory Address Vector Context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_MRAV UINT32_C(0xe) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_MRAV UINT32_C(0xe) /* TIM. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TIM UINT32_C(0xf) - /* Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TKC UINT32_C(0x13) - /* Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_RKC UINT32_C(0x14) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TIM UINT32_C(0xf) + /* Tx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TX_CK UINT32_C(0x13) + /* Rx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_RX_CK UINT32_C(0x14) /* Mid-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_MP_TQM_RING UINT32_C(0x15) - /* QUIC Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_QUIC_TKC UINT32_C(0x1a) - /* QUIC Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_QUIC_RKC UINT32_C(0x1b) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_MP_TQM_RING UINT32_C(0x15) + /* CFA table scope context. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TBL_SCOPE UINT32_C(0x1c) + /* XID partition context. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_XID_PARTITION UINT32_C(0x1d) + /* SRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT_TRACE UINT32_C(0x1e) + /* SRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT2_TRACE UINT32_C(0x1f) + /* CRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CRT_TRACE UINT32_C(0x20) + /* CRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CRT2_TRACE UINT32_C(0x21) + /* RIGP0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_RIGP0_TRACE UINT32_C(0x22) + /* L2 HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x23) + /* RoCE HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x24) + /* TimedTx pacing TQM ring. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_TTX_PACING_TQM_RING UINT32_C(0x25) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CA0_TRACE UINT32_C(0x26) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CA1_TRACE UINT32_C(0x27) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CA2_TRACE UINT32_C(0x28) + /* RIGP1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_RIGP1_TRACE UINT32_C(0x29) /* Invalid type. */ - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_INVALID UINT32_C(0xffff) - #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_INVALID + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_INVALID UINT32_C(0xffff) + #define HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_INVALID /* * Instance of the backing store type. It is zero-based, * which means "0" indicates the first instance. For backing * stores with single instance only, leave this field to 0. + * 1. If the backing store type is MPC TQM ring, use the following + * instance value to map to MPC clients: + * TCE (0), RCE (1), TE_CFA(2), RE_CFA (3), PRIMATE(4) + * 2. If the backing store type is TBL_SCOPE, use the following + * instance value to map to table scope regions: + * RE_CFA_LKUP (0), RE_CFA_ACT (1), TE_CFA_LKUP(2), TE_CFA_ACT (3) + * 3. If the backing store type is XID partition, use the following + * instance value to map to context types: + * TX_CK (0), RX_CK (1) */ uint16_t instance; /* Control flags. */ @@ -21521,7 +23428,9 @@ typedef struct hwrm_func_backing_store_qcfg_v2_output { * | SRQ | srq_split_entries | * | CQ | cq_split_entries | * | VINC | vnic_split_entries | - * | MRAV | marv_split_entries | + * | MRAV | mrav_split_entries | + * | TS | ts_split_entries | + * | CK | ck_split_entries | */ uint32_t split_entry_0; /* Split entry #1. */ @@ -21533,7 +23442,7 @@ typedef struct hwrm_func_backing_store_qcfg_v2_output { uint8_t rsvd2[7]; /* * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be + * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been completely * written. When writing a command completion or response to * an internal processor, the order of writes has to be such @@ -21550,7 +23459,12 @@ typedef struct qpc_split_entries { uint32_t qp_num_l2_entries; /* Number of QP1 entries. */ uint32_t qp_num_qp1_entries; - uint64_t rsvd; + /* + * Number of RoCE QP context entries required for this + * function to support fast QP modify destroy feature. + */ + uint32_t qp_num_fast_qpmd_entries; + uint32_t rsvd; } qpc_split_entries_t, *pqpc_split_entries_t; /* Common structure to cast SRQ split entries. This casting is required in the following HWRM command inputs/outputs if the backing store type is SRQ. 1. hwrm_func_backing_store_cfg_v2_input 2. hwrm_func_backing_store_qcfg_v2_output 3. hwrm_func_backing_store_qcaps_v2_output */ @@ -21593,6 +23507,37 @@ typedef struct mrav_split_entries { uint64_t rsvd2; } mrav_split_entries_t, *pmrav_split_entries_t; +/* Common structure to cast TBL_SCOPE split entries. This casting is required in the following HWRM command inputs/outputs if the backing store type is TBL_SCOPE. 1. hwrm_func_backing_store_cfg_v2_input 2. hwrm_func_backing_store_qcfg_v2_output 3. hwrm_func_backing_store_qcaps_v2_output */ +/* ts_split_entries (size:128b/16B) */ + +typedef struct ts_split_entries { + /* Max number of TBL_SCOPE region entries (QCAPS). */ + uint32_t region_num_entries; + /* tsid to configure (CFG). */ + uint8_t tsid; + /* + * Lkup static bucket count (power of 2). + * Array is indexed by enum cfa_dir + */ + uint8_t lkup_static_bkt_cnt_exp[2]; + uint8_t rsvd; + uint64_t rsvd2; +} ts_split_entries_t, *pts_split_entries_t; + +/* Common structure to cast crypto key split entries. This casting is required in the following HWRM command inputs/outputs if the backing store type is TX_CK or RX_CK. 1. hwrm_func_backing_store_cfg_v2_input 2. hwrm_func_backing_store_qcfg_v2_output 3. hwrm_func_backing_store_qcaps_v2_output */ +/* ck_split_entries (size:128b/16B) */ + +typedef struct ck_split_entries { + /* + * Number of QUIC backing store entries. That means the number of KTLS + * backing store entries is the difference between this number and the + * total number of crypto key entries. + */ + uint32_t num_quic_entries; + uint32_t rsvd; + uint64_t rsvd2; +} ck_split_entries_t, *pck_split_entries_t; + /************************************ * hwrm_func_backing_store_qcaps_v2 * ************************************/ @@ -21634,42 +23579,66 @@ typedef struct hwrm_func_backing_store_qcaps_v2_input { /* Queue pair. */ #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_QP UINT32_C(0x0) /* Shared receive queue. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRQ UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRQ UINT32_C(0x1) /* Completion queue. */ #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CQ UINT32_C(0x2) /* Virtual NIC. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_VNIC UINT32_C(0x3) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_VNIC UINT32_C(0x3) /* Statistic context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_STAT UINT32_C(0x4) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_STAT UINT32_C(0x4) /* Slow-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SP_TQM_RING UINT32_C(0x5) /* Fast-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_FP_TQM_RING UINT32_C(0x6) /* Memory Region and Memory Address Vector Context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_MRAV UINT32_C(0xe) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_MRAV UINT32_C(0xe) /* TIM. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TIM UINT32_C(0xf) - /* Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TKC UINT32_C(0x13) - /* Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RKC UINT32_C(0x14) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TIM UINT32_C(0xf) + /* Tx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TX_CK UINT32_C(0x13) + /* Rx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RX_CK UINT32_C(0x14) /* Mid-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_MP_TQM_RING UINT32_C(0x15) /* SQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) /* RQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) /* SRQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) /* CQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) - /* QUIC Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_QUIC_TKC UINT32_C(0x1a) - /* QUIC Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_QUIC_RKC UINT32_C(0x1b) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) + /* CFA table scope context. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TBL_SCOPE UINT32_C(0x1c) + /* XID partition context. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_XID_PARTITION UINT32_C(0x1d) + /* SRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRT_TRACE UINT32_C(0x1e) + /* SRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_SRT2_TRACE UINT32_C(0x1f) + /* CRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CRT_TRACE UINT32_C(0x20) + /* CRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CRT2_TRACE UINT32_C(0x21) + /* RIGP0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RIGP0_TRACE UINT32_C(0x22) + /* L2 HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x23) + /* RoCE HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x24) + /* TimedTx pacing TQM ring. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_TTX_PACING_TQM_RING UINT32_C(0x25) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CA0_TRACE UINT32_C(0x26) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CA1_TRACE UINT32_C(0x27) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_CA2_TRACE UINT32_C(0x28) + /* RIGP1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_RIGP1_TRACE UINT32_C(0x29) /* Invalid type. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_INVALID + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_INVALID UINT32_C(0xffff) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCAPS_V2_INPUT_TYPE_INVALID uint8_t rsvd[6]; } hwrm_func_backing_store_qcaps_v2_input_t, *phwrm_func_backing_store_qcaps_v2_input_t; @@ -21689,53 +23658,77 @@ typedef struct hwrm_func_backing_store_qcaps_v2_output { /* Queue pair. */ #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_QP UINT32_C(0x0) /* Shared receive queue. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRQ UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRQ UINT32_C(0x1) /* Completion queue. */ #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CQ UINT32_C(0x2) /* Virtual NIC. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_VNIC UINT32_C(0x3) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_VNIC UINT32_C(0x3) /* Statistic context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_STAT UINT32_C(0x4) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_STAT UINT32_C(0x4) /* Slow-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SP_TQM_RING UINT32_C(0x5) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SP_TQM_RING UINT32_C(0x5) /* Fast-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_FP_TQM_RING UINT32_C(0x6) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_FP_TQM_RING UINT32_C(0x6) /* Memory Region and Memory Address Vector Context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_MRAV UINT32_C(0xe) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_MRAV UINT32_C(0xe) /* TIM. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TIM UINT32_C(0xf) - /* KTLS Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TKC UINT32_C(0x13) - /* KTLS Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RKC UINT32_C(0x14) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TIM UINT32_C(0xf) + /* Tx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TX_CK UINT32_C(0x13) + /* Rx crypto key. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RX_CK UINT32_C(0x14) /* Mid-path TQM ring. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_MP_TQM_RING UINT32_C(0x15) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_MP_TQM_RING UINT32_C(0x15) /* SQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SQ_DB_SHADOW UINT32_C(0x16) /* RQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RQ_DB_SHADOW UINT32_C(0x17) /* SRQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRQ_DB_SHADOW UINT32_C(0x18) /* CQ Doorbell shadow region. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) - /* QUIC Tx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_QUIC_TKC UINT32_C(0x1a) - /* QUIC Rx key context. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_QUIC_RKC UINT32_C(0x1b) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CQ_DB_SHADOW UINT32_C(0x19) + /* CFA table scope context. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TBL_SCOPE UINT32_C(0x1c) + /* XID partition context. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_XID_PARTITION UINT32_C(0x1d) + /* SRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRT_TRACE UINT32_C(0x1e) + /* SRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_SRT2_TRACE UINT32_C(0x1f) + /* CRT trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CRT_TRACE UINT32_C(0x20) + /* CRT2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CRT2_TRACE UINT32_C(0x21) + /* RIGP0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RIGP0_TRACE UINT32_C(0x22) + /* L2 HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x23) + /* RoCE HWRM trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x24) + /* TimedTx pacing TQM ring. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_TTX_PACING_TQM_RING UINT32_C(0x25) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CA0_TRACE UINT32_C(0x26) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CA1_TRACE UINT32_C(0x27) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_CA2_TRACE UINT32_C(0x28) + /* RIGP1 trace. */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_RIGP1_TRACE UINT32_C(0x29) /* Invalid type. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_INVALID UINT32_C(0xffff) - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_INVALID + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_INVALID UINT32_C(0xffff) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_LAST HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_TYPE_INVALID /* Number of bytes per backing store entry. */ uint16_t entry_size; /* Control flags. */ uint32_t flags; /* * When set, it indicates the context type should be initialized - * with the “ctx_init_value” at the specified offset. + * with the 'ctx_init_value' at the specified offset. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_ENABLE_CTX_KIND_INIT UINT32_C(0x1) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_ENABLE_CTX_KIND_INIT UINT32_C(0x1) /* When set, it indicates the context type is valid. */ - #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_TYPE_VALID UINT32_C(0x2) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_TYPE_VALID UINT32_C(0x2) /* * When set, it indicates the region for this type is not a regular * context memory but a driver managed memory that is created, @@ -21743,11 +23736,39 @@ typedef struct hwrm_func_backing_store_qcaps_v2_output { */ #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_DRIVER_MANAGED_MEMORY UINT32_C(0x4) /* + * When set, it indicates the support of the following capability + * that is specific to the QP type: + * - For 2-port adapters, the ability to extend the RoCE QP + * entries configured on a PF, during some network events such as + * Link Down. These additional entries count is included in the + * advertised 'max_num_entries'. + * - The count of RoCE QP entries, derived from 'max_num_entries' + * (max_num_entries - qp_num_qp1_entries - qp_num_l2_entries - + * qp_num_fast_qpmd_entries, note qp_num_fast_qpmd_entries is + * always zero when QPs are pseudo-statically allocated), includes + * the count of QPs that can be migrated from the other PF (e.g., + * during network link down). Therefore, during normal operation + * when both PFs are active, the supported number of RoCE QPs for + * each of the PF is half of the advertised value. + */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_ROCE_QP_PSEUDO_STATIC_ALLOC UINT32_C(0x8) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_FW_DBG_TRACE UINT32_C(0x10) + + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_FW_BIN_DBG_TRACE UINT32_C(0x20) + + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_NEXT_BS_OFFSET UINT32_C(0x40) + /* * Bit map of the valid instances associated with the * backing store type. * 1. If the backing store type is MPC TQM ring, use the following - * bit to MPC client mapping: + * bits to map to MPC clients: * TCE (0), RCE (1), TE_CFA(2), RE_CFA (3), PRIMATE(4) + * 2. If the backing store type is TBL_SCOPE, use the following + * bits to map to table scope regions: + * RE_CFA_LKUP (0), RE_CFA_ACT (1), TE_CFA_LKUP(2), TE_CFA_ACT (3) + * 3. If the backing store type is VF XID partition in-use table, use + * the following bits to map to context types: + * TX_CK (0), RX_CK (1) */ uint32_t instance_bit_map; /* @@ -21794,7 +23815,37 @@ typedef struct hwrm_func_backing_store_qcaps_v2_output { * | 4 | All four split entries have valid data. | */ uint8_t subtype_valid_cnt; - uint8_t rsvd2; + /* + * Bitmap that indicates if each of the 'split_entry' denotes an + * exact count (i.e., min = max). When the exact count bit is set, + * it indicates the exact number of entries as advertised has to be + * configured. The 'split_entry' to be set to contain exact count by + * this bitmap needs to be a valid split entry specified by + * 'subtype_valid_cnt'. + */ + uint8_t exact_cnt_bit_map; + /* + * When this bit is '1', it indicates 'split_entry_0' contains + * an exact count. + */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_SPLIT_ENTRY_0_EXACT UINT32_C(0x1) + /* + * When this bit is '1', it indicates 'split_entry_1' contains + * an exact count. + */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_SPLIT_ENTRY_1_EXACT UINT32_C(0x2) + /* + * When this bit is '1', it indicates 'split_entry_2' contains + * an exact count. + */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_SPLIT_ENTRY_2_EXACT UINT32_C(0x4) + /* + * When this bit is '1', it indicates 'split_entry_3' contains + * an exact count. + */ + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_SPLIT_ENTRY_3_EXACT UINT32_C(0x8) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_UNUSED_MASK UINT32_C(0xf0) + #define HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_EXACT_CNT_BIT_MAP_UNUSED_SFT 4 /* * Split entry #0. Note that the four split entries (as a group) * must be cast to a type-specific data structure first before @@ -21806,7 +23857,8 @@ typedef struct hwrm_func_backing_store_qcaps_v2_output { * | SRQ | srq_split_entries | * | CQ | cq_split_entries | * | VINC | vnic_split_entries | - * | MRAV | marv_split_entries | + * | MRAV | mrav_split_entries | + * | TS | ts_split_entries | */ uint32_t split_entry_0; /* Split entry #1. */ @@ -21818,7 +23870,7 @@ typedef struct hwrm_func_backing_store_qcaps_v2_output { uint8_t rsvd3[3]; /* * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be + * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been completely * written. When writing a command completion or response to * an internal processor, the order of writes has to be such @@ -21885,7 +23937,7 @@ typedef struct hwrm_func_dbr_pacing_cfg_input { */ #define HWRM_FUNC_DBR_PACING_CFG_INPUT_ENABLES_PACING_THRESHOLD_VALID UINT32_C(0x2) /* - * Specify primary function’s NQ ID to receive the doorbell pacing + * Specify primary function's NQ ID to receive the doorbell pacing * threshold crossing events. */ uint32_t primary_nq_id; @@ -21911,7 +23963,7 @@ typedef struct hwrm_func_dbr_pacing_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -22083,9 +24135,10 @@ typedef struct hwrm_func_dbr_pacing_qcfg_output { */ uint8_t dbr_throttling_aeq_arm_reg_val; uint8_t unused_3[3]; - uint32_t dbr_stat_db_max_fifo_depth; + /* This field indicates the maximum depth of the doorbell FIFO. */ + uint32_t dbr_stat_db_max_fifo_depth; /* - * Specifies primary function’s NQ ID. + * Specifies primary function's NQ ID. * A value of 0xFFFF FFFF indicates NQ ID is invalid. */ uint32_t primary_nq_id; @@ -22097,7 +24150,7 @@ typedef struct hwrm_func_dbr_pacing_qcfg_output { uint8_t unused_4[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -22158,7 +24211,7 @@ typedef struct hwrm_func_dbr_pacing_broadcast_event_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -22253,9 +24306,9 @@ typedef struct hwrm_func_dbr_pacing_nqlist_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22323,7 +24376,7 @@ typedef struct hwrm_func_dbr_recovery_completed_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -22428,9 +24481,9 @@ typedef struct hwrm_func_synce_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22510,14 +24563,817 @@ typedef struct hwrm_func_synce_qcfg_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; } hwrm_func_synce_qcfg_output_t, *phwrm_func_synce_qcfg_output_t; +/************************ + * hwrm_func_lag_create * + ************************/ + + +/* hwrm_func_lag_create_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_create_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint8_t enables; + /* + * This bit must be '1' for the active_port_map field to be + * configured. + */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ENABLES_ACTIVE_PORT_MAP UINT32_C(0x1) + /* + * This bit must be '1' for the member_port_map field to be + * configured. + */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ENABLES_MEMBER_PORT_MAP UINT32_C(0x2) + /* This bit must be '1' for the aggr_mode field to be configured. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ENABLES_AGGR_MODE UINT32_C(0x4) + /* rsvd1 is 5 b */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ENABLES_RSVD1_MASK UINT32_C(0xf8) + #define HWRM_FUNC_LAG_CREATE_INPUT_ENABLES_RSVD1_SFT 3 + /* + * This is the bitmap of all active ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. The active_port_map must always be a subset of the + * member_port_map. An active port is eligible to send and receive + * traffic. + * + * If the LAG mode is active-backup, only one port can be an active + * port at a given time. All other ports in the member_port_map that + * are not the active port are backup port. When the active port + * fails, another member port takes over to become the active port. + * The driver should use HWRM_FUNC_LAG_UPDATE to update + * the active_port_map by only setting the port bit of the new active + * port. + * + * In active-active, balance_xor or 802_3_ad mode, all member ports + * can be active ports. If the driver determines that an active + * port is down or unable to function, it should use + * HWRM_FUNC_LAG_UPDATE to update the active_port_map by clearing + * the port bit that has failed. + */ + uint8_t active_port_map; + /* If this bit is set to '1', the port0 is a lag active port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag active port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag active port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag active port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd3 is 4 b */ + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_RSVD3_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_CREATE_INPUT_ACTIVE_PORT_MAP_RSVD3_SFT 4 + /* + * This is the bitmap of all member ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. There must be at least 2 ports in the member ports and + * each must not be a member of another LAG. Note that on a 4-port + * device, there can be either 2 ports or 4 ports in the member ports. + * Using 3 member ports is not supported. + */ + uint8_t member_port_map; + /* If this bit is set to '1', the port0 is a lag member port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag member port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag member port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag member port. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd4 is 4 b */ + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_RSVD4_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_CREATE_INPUT_MEMBER_PORT_MAP_RSVD4_SFT 4 + /* Link aggregation mode being used. */ + uint8_t link_aggr_mode; + /* active active mode. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_ACTIVE_ACTIVE UINT32_C(0x1) + /* active backup mode. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_ACTIVE_BACKUP UINT32_C(0x2) + /* Balance XOR mode. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_BALANCE_XOR UINT32_C(0x3) + /* 802.3AD mode. */ + #define HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_802_3_AD UINT32_C(0x4) + #define HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_LAST HWRM_FUNC_LAG_CREATE_INPUT_AGGR_MODE_802_3_AD + uint8_t unused_0[4]; +} hwrm_func_lag_create_input_t, *phwrm_func_lag_create_input_t; + +/* hwrm_func_lag_create_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_create_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * LAG ID of the created LAG. This LAG ID will also be returned + * in the HWRM_FUNC_QCFG response of all member ports. + */ + uint8_t fw_lag_id; + uint8_t unused_0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_create_output_t, *phwrm_func_lag_create_output_t; + +/************************ + * hwrm_func_lag_update * + ************************/ + + +/* hwrm_func_lag_update_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_update_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Link aggregation group ID of the LAG to be updated. */ + uint8_t fw_lag_id; + uint8_t enables; + /* + * This bit must be '1' for the active_port_map field to be + * updated. + */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ENABLES_ACTIVE_PORT_MAP UINT32_C(0x1) + /* + * This bit must be '1' for the member_port_map field to be + * updated. + */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ENABLES_MEMBER_PORT_MAP UINT32_C(0x2) + /* This bit must be '1' for the aggr_mode field to be updated. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ENABLES_AGGR_MODE UINT32_C(0x4) + /* rsvd1 is 5 b */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ENABLES_RSVD1_MASK UINT32_C(0xf8) + #define HWRM_FUNC_LAG_UPDATE_INPUT_ENABLES_RSVD1_SFT 3 + /* + * This is the bitmap of all active ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. The active_port_map must always be a subset of the + * member_port_map. An active port is eligible to send and receive + * traffic. + * + * If the LAG mode is active-backup, only one port can be an active + * port at a given time. All other ports in the member_port_map that + * are not the active port are backup port. When the active port + * fails, another member port takes over to become the active port. + * The driver should use HWRM_FUNC_LAG_UPDATE to update + * the active_port_map by only setting the port bit of the new active + * port. + * + * In active-active, balance_xor or 802_3_ad mode, all member ports + * can be active ports. If the driver determines that an active + * port is down or unable to function, it should use + * HWRM_FUNC_LAG_UPDATE to update the active_port_map by clearing + * the port bit that has failed. + */ + uint8_t active_port_map; + /* If this bit is set to '1', the port0 is a lag active port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag active port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag active port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag active port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd3 is 4 b */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_RSVD3_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_UPDATE_INPUT_ACTIVE_PORT_MAP_RSVD3_SFT 4 + /* + * This is the bitmap of all member ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. There must be at least 2 ports in the member ports and + * each must not be a member of another LAG. Note that on a 4-port + * device, there can be either 2 ports or 4 ports in the member ports. + * Using 3 member ports is not supported. + */ + uint8_t member_port_map; + /* If this bit is set to '1', the port0 is a lag member port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag member port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag member port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag member port. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd4 is 4 b */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_RSVD4_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_UPDATE_INPUT_MEMBER_PORT_MAP_RSVD4_SFT 4 + /* Link aggregation mode being used. */ + uint8_t link_aggr_mode; + /* active active mode. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_ACTIVE_ACTIVE UINT32_C(0x1) + /* active backup mode. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_ACTIVE_BACKUP UINT32_C(0x2) + /* Balance XOR mode. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_BALANCE_XOR UINT32_C(0x3) + /* 802.3AD mode. */ + #define HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_802_3_AD UINT32_C(0x4) + #define HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_LAST HWRM_FUNC_LAG_UPDATE_INPUT_AGGR_MODE_802_3_AD + uint8_t unused_0[3]; +} hwrm_func_lag_update_input_t, *phwrm_func_lag_update_input_t; + +/* hwrm_func_lag_update_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_update_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_update_output_t, *phwrm_func_lag_update_output_t; + +/********************** + * hwrm_func_lag_free * + **********************/ + + +/* hwrm_func_lag_free_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_free_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Link aggregation group ID of the LAG to be freed. */ + uint8_t fw_lag_id; + uint8_t unused_0[7]; +} hwrm_func_lag_free_input_t, *phwrm_func_lag_free_input_t; + +/* hwrm_func_lag_free_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_free_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_free_output_t, *phwrm_func_lag_free_output_t; + +/********************** + * hwrm_func_lag_qcfg * + **********************/ + + +/* hwrm_func_lag_qcfg_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Link aggregation group ID of the LAG to be queried. */ + uint8_t fw_lag_id; + uint8_t unused_0[7]; +} hwrm_func_lag_qcfg_input_t, *phwrm_func_lag_qcfg_input_t; + +/* hwrm_func_lag_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This is the bitmap of all active ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. The active_port_map must always be a subset of the + * member_port_map. An active port is eligible to send and receive + * traffic. + * + * If the LAG mode is active-backup, only one port can be an active + * port at a given time. All other ports in the member_port_map that + * are not the active port are backup port. When the active port + * fails, another member port takes over to become the active port. + * The driver should use HWRM_FUNC_LAG_UPDATE to update + * the active_port_map by only setting the port bit of the new active + * port. + * + * In active-active, balance_xor or 802_3_ad mode, all member ports + * can be active ports. If the driver determines that an active + * port is down or unable to function, it should use + * HWRM_FUNC_LAG_UPDATE to update the active_port_map by clearing + * the port bit that has failed. + */ + uint8_t active_port_map; + /* If this bit is set to '1', the port0 is a lag active port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag active port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag active port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag active port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd3 is 4 b */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_RSVD3_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_QCFG_OUTPUT_ACTIVE_PORT_MAP_RSVD3_SFT 4 + /* + * This is the bitmap of all member ports in the LAG. Each bit + * represents a front panel port of the device. Ports are numbered + * from 0 to n - 1 on a device with n ports. The number of front panel + * ports is specified in the port_cnt field of the HWRM_PORT_PHY_QCAPS + * response. There must be at least 2 ports in the member ports and + * each must not be a member of another LAG. Note that on a 4-port + * device, there can be either 2 ports or 4 ports in the member ports. + * Using 3 member ports is not supported. + */ + uint8_t member_port_map; + /* If this bit is set to '1', the port0 is a lag member port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag member port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag member port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag member port. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd4 is 4 b */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_RSVD4_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_QCFG_OUTPUT_MEMBER_PORT_MAP_RSVD4_SFT 4 + /* Link aggregation mode being used. */ + uint8_t link_aggr_mode; + /* active active mode. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_ACTIVE_ACTIVE UINT32_C(0x1) + /* active backup mode. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_ACTIVE_BACKUP UINT32_C(0x2) + /* Balance XOR mode. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_BALANCE_XOR UINT32_C(0x3) + /* 802.3AD mode. */ + #define HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_802_3_AD UINT32_C(0x4) + #define HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_LAST HWRM_FUNC_LAG_QCFG_OUTPUT_AGGR_MODE_802_3_AD + uint8_t unused_0[4]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_qcfg_output_t, *phwrm_func_lag_qcfg_output_t; + +/************************** + * hwrm_func_lag_mode_cfg * + **************************/ + + +/* hwrm_func_lag_mode_cfg_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_mode_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint8_t enables; + /* + * This bit must be '1' for the link aggregation enable or + * disable flags to be configured. + */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_FLAGS UINT32_C(0x1) + /* + * This bit must be '1' for the active_port_map field to be + * configured. + */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_ACTIVE_PORT_MAP UINT32_C(0x2) + /* + * This bit must be '1' for the member_port_map field to be + * configured. + */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_MEMBER_PORT_MAP UINT32_C(0x4) + /* This bit must be '1' for the aggr_mode field to be configured. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_AGGR_MODE UINT32_C(0x8) + /* This bit must be '1' for the lag id field to be configured. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_LAG_ID UINT32_C(0x10) + /* rsvd1 is 3 b */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_RSVD1_MASK UINT32_C(0xe0) + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ENABLES_RSVD1_SFT 5 + uint8_t flags; + /* + * If this bit is set to 1, the driver is requesting FW to disable + * link aggregation feature during run time. + */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_FLAGS_AGGR_DISABLE UINT32_C(0x1) + /* + * If this bit is set to 1, the driver is requesting FW to enable + * link aggregation feature during run time. + */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_FLAGS_AGGR_ENABLE UINT32_C(0x2) + /* rsvd2 is 6 b */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_FLAGS_RSVD2_MASK UINT32_C(0xfc) + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_FLAGS_RSVD2_SFT 2 + /* + * This is the bitmap of all active ports in the LAG. Each bit + * represents a front panel port of the device starting from port 0. + * The number of front panel ports is specified in the port_cnt field + * of the HWRM_PORT_PHY_QCAPS response. + * The term "active port" is one of member ports which is eligible to + * send or receive the traffic. + * In the active-backup mode, only one member port is active port at + * any given time. If the active port fails, another member port + * automatically takes over the active role to ensure continuous + * network connectivity. + * In the active-active, balance_xor or 802_3_ad mode, all member ports + * could be active port, if link status on one port is down, driver + * needs to send the NIC a new active-port bitmap with marking this + * port as not active port. + * The PORT_2 and PORT_3 are only valid if the NIC has four front + * panel ports. + */ + uint8_t active_port_map; + /* If this bit is set to '1', the port0 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd3 is 4 b */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_RSVD3_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_ACTIVE_PORT_MAP_RSVD3_SFT 4 + /* + * This is the bitmap of all member ports in the LAG. Each bit + * represents a front panel port of the device starting from port 0. + * The number of front panel ports is specified in the port_cnt field + * of the HWRM_PORT_PHY_QCAPS response. + * The term "member port" refers to a front panel port that is added to + * the bond group as a slave device. These member ports are combined to + * create a logical bond interface. + * For a 4-port NIC, the LAG member port combination can consist of + * either two ports or four ports. However, it is important to note + * that the case with three ports in the same lag group is not + * supported. + * The PORT_2 and PORT_3 are only valid if the NIC has four front + * panel ports. There could be a case to use multiple LAG groups, + * for example, if the NIC has four front panel ports, the lag feature + * can use up to two LAG groups, with two ports assigned to each group. + */ + uint8_t member_port_map; + /* If this bit is set to '1', the port0 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd4 is 4 b */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_RSVD4_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_MEMBER_PORT_MAP_RSVD4_SFT 4 + /* Link aggregation mode being used. */ + uint8_t link_aggr_mode; + /* active active mode. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_ACTIVE_ACTIVE UINT32_C(0x1) + /* active backup mode. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_ACTIVE_BACKUP UINT32_C(0x2) + /* Balance XOR mode. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_BALANCE_XOR UINT32_C(0x3) + /* 802.3AD mode. */ + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_802_3_AD UINT32_C(0x4) + #define HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_LAST HWRM_FUNC_LAG_MODE_CFG_INPUT_AGGR_MODE_802_3_AD + /* Link aggregation group idx being used. */ + uint8_t lag_id; + uint8_t unused_0[2]; +} hwrm_func_lag_mode_cfg_input_t, *phwrm_func_lag_mode_cfg_input_t; + +/* hwrm_func_lag_mode_cfg_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_mode_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Link aggregation group idx being used. */ + uint8_t lag_id; + uint8_t unused_0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_mode_cfg_output_t, *phwrm_func_lag_mode_cfg_output_t; + +/*************************** + * hwrm_func_lag_mode_qcfg * + ***************************/ + + +/* hwrm_func_lag_mode_qcfg_input (size:192b/24B) */ + +typedef struct hwrm_func_lag_mode_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint8_t unused_0[8]; +} hwrm_func_lag_mode_qcfg_input_t, *phwrm_func_lag_mode_qcfg_input_t; + +/* hwrm_func_lag_mode_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_func_lag_mode_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t aggr_enabled; + /* + * This flag is used to query whether link aggregation is enabled + * or disabled during run time. + */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_ENABLED UINT32_C(0x1) + /* rsvd1 is 7 b */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_RSVD1_MASK UINT32_C(0xfe) + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_RSVD1_SFT 1 + /* + * This is the bitmap of all active ports in the LAG. Each bit + * represents a front panel port of the device starting from port 0. + * The number of front panel ports is specified in the port_cnt field + * of the HWRM_PORT_PHY_QCAPS response. + * The term "active port" is one of member ports which is eligible to + * send or receive the traffic. + * In the active-backup mode, only one member port is active port at + * any given time. If the active port fails, another member port + * automatically takes over the active role to ensure continuous + * network connectivity. + * In the active-active, balance_xor or 802_3_ad mode, all member ports + * could be active port, if link status on one port is down, driver + * needs to send the NIC a new active-port bitmap with marking this + * port as not active port. + * The PORT_2 and PORT_3 are only valid if the NIC has four front + * panel ports. + */ + uint8_t active_port_map; + /* If this bit is set to '1', the port0 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag active port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd2 is 4 b */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_RSVD2_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_ACTIVE_PORT_MAP_RSVD2_SFT 4 + /* + * This is the bitmap of all member ports in the LAG. Each bit + * represents a front panel port of the device starting from port 0. + * The number of front panel ports is specified in the port_cnt field + * of the HWRM_PORT_PHY_QCAPS response. + * The term "member port" refers to a front panel port that is added to + * the bond group as a slave device. These member ports are combined to + * create a logical bond interface. + * For a 4-port NIC, the LAG member port combination can consist of + * either two ports or four ports. However, it is important to note + * that the case with three ports in the same lag group is not + * supported. + * The PORT_2 and PORT_3 are only valid if the NIC has four front + * panel ports. There could be a case to use multiple LAG groups, + * for example, if the NIC has four front panel ports, the lag feature + * can use up to two LAG groups, with two ports assigned to each group. + */ + uint8_t member_port_map; + /* If this bit is set to '1', the port0 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_0 UINT32_C(0x1) + /* If this bit is set to '1', the port1 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_1 UINT32_C(0x2) + /* If this bit is set to '1', the port2 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_2 UINT32_C(0x4) + /* If this bit is set to '1', the port3 is a lag member port. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_PORT_3 UINT32_C(0x8) + /* rsvd3 is 4 b */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_RSVD3_MASK UINT32_C(0xf0) + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_MEMBER_PORT_MAP_RSVD3_SFT 4 + /* Link aggregation mode being used. */ + uint8_t link_aggr_mode; + /* active active mode. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_ACTIVE_ACTIVE UINT32_C(0x1) + /* active backup mode. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_ACTIVE_BACKUP UINT32_C(0x2) + /* Balance XOR mode. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_BALANCE_XOR UINT32_C(0x3) + /* 802.3AD mode. */ + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_802_3_AD UINT32_C(0x4) + #define HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_LAST HWRM_FUNC_LAG_MODE_QCFG_OUTPUT_AGGR_MODE_802_3_AD + uint8_t unused_0[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_func_lag_mode_qcfg_output_t, *phwrm_func_lag_mode_qcfg_output_t; + /*********************** * hwrm_func_vlan_qcfg * ***********************/ @@ -22582,8 +25438,8 @@ typedef struct hwrm_func_vlan_qcfg_output { uint8_t stag_pcp; uint8_t unused_1; /* - * S-TAG TPID value configured for the function. This field is specified in - * network byte order. + * S-TAG TPID value configured for the function. This field is + * specified in network byte order. */ uint16_t stag_tpid; /* C-TAG VLAN identifier configured for the function. */ @@ -22592,8 +25448,8 @@ typedef struct hwrm_func_vlan_qcfg_output { uint8_t ctag_pcp; uint8_t unused_2; /* - * C-TAG TPID value configured for the function. This field is specified in - * network byte order. + * C-TAG TPID value configured for the function. This field is + * specified in network byte order. */ uint16_t ctag_tpid; /* Future use. */ @@ -22603,9 +25459,9 @@ typedef struct hwrm_func_vlan_qcfg_output { uint8_t unused_3[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22692,8 +25548,8 @@ typedef struct hwrm_func_vlan_cfg_input { uint8_t stag_pcp; uint8_t unused_1; /* - * S-TAG TPID value configured for the function. This field is specified in - * network byte order. + * S-TAG TPID value configured for the function. This field is + * specified in network byte order. */ uint16_t stag_tpid; /* C-TAG VLAN identifier configured for the function. */ @@ -22702,8 +25558,8 @@ typedef struct hwrm_func_vlan_cfg_input { uint8_t ctag_pcp; uint8_t unused_2; /* - * C-TAG TPID value configured for the function. This field is specified in - * network byte order. + * C-TAG TPID value configured for the function. This field is + * specified in network byte order. */ uint16_t ctag_tpid; /* Future use. */ @@ -22727,9 +25583,9 @@ typedef struct hwrm_func_vlan_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22803,9 +25659,9 @@ typedef struct hwrm_func_vf_vnic_ids_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22913,9 +25769,9 @@ typedef struct hwrm_func_vf_bw_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -22984,8 +25840,8 @@ typedef struct hwrm_func_vf_bw_qcfg_output { uint16_t resp_len; /* * The number of VF functions that are being queried. - * The inline response space allows the host to query up to 50 VFs' rate - * scale percentage + * The inline response space allows the host to query up to 50 VFs' + * rate scale percentage. */ uint16_t num_vfs; uint16_t unused[3]; @@ -23036,9 +25892,9 @@ typedef struct hwrm_func_vf_bw_qcfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -23083,11 +25939,11 @@ typedef struct hwrm_func_drv_if_change_input { uint32_t flags; /* * When this bit is '1', the function driver is indicating - * that the IF state is changing to UP state. The call should + * that the IF state is changing to UP state. The call should * be made at the beginning of the driver's open call before - * resources are allocated. After making the call, the driver + * resources are allocated. After making the call, the driver * should check the response to see if any resources may have - * changed (see the response below). If the driver fails + * changed (see the response below). If the driver fails * the open call, the driver should make this call again with * this bit cleared to indicate that the IF state is not UP. * During the driver's close call when the IF state is changing @@ -23112,22 +25968,32 @@ typedef struct hwrm_func_drv_if_change_output { uint32_t flags; /* * When this bit is '1', it indicates that the resources reserved - * for this function may have changed. The driver should check + * for this function may have changed. The driver should check * resource capabilities and reserve resources again before * allocating resources. */ #define HWRM_FUNC_DRV_IF_CHANGE_OUTPUT_FLAGS_RESC_CHANGE UINT32_C(0x1) /* - * When this bit is '1', it indicates that the firmware got changed / reset. - * The driver should do complete re-initialization when that bit is set. + * When this bit is '1', it indicates that the firmware got changed / + * reset. The driver should do complete re-initialization when that + * bit is set. */ #define HWRM_FUNC_DRV_IF_CHANGE_OUTPUT_FLAGS_HOT_FW_RESET_DONE UINT32_C(0x2) + /* + * When this bit is '1', it indicates that capabilities + * for this function may have changed. The driver should + * query for changes to capabilities. + * The CAPS_CHANGE bit will only be set when it is safe for the + * driver to completely re-initialize all resources for the function + * including any children VFs. + */ + #define HWRM_FUNC_DRV_IF_CHANGE_OUTPUT_FLAGS_CAPS_CHANGE UINT32_C(0x4) uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -23316,9 +26182,9 @@ typedef struct hwrm_func_host_pf_ids_query_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -23513,9 +26379,9 @@ typedef struct hwrm_func_spd_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -23673,9 +26539,9 @@ typedef struct hwrm_func_spd_qcfg_output { uint8_t unused_2[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -23686,7 +26552,7 @@ typedef struct hwrm_func_spd_qcfg_output { *********************/ -/* hwrm_port_phy_cfg_input (size:448b/56B) */ +/* hwrm_port_phy_cfg_input (size:512b/64B) */ typedef struct hwrm_port_phy_cfg_input { /* The HWRM command request type. */ @@ -23733,7 +26599,7 @@ typedef struct hwrm_port_phy_cfg_input { * settings specified in this command. */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY UINT32_C(0x1) - /* deprecated bit. Do not use!!! */ + /* deprecated bit. Do not use!!! */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_DEPRECATED UINT32_C(0x2) /* * When this bit is set to '1', and the force_pam4_link_speed @@ -23793,33 +26659,33 @@ typedef struct hwrm_port_phy_cfg_input { */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI_DISABLE UINT32_C(0x80) /* - * When set to 1, then the HWRM shall enable FEC autonegotitation - * on this port if supported. When enabled, at least one of the + * When set to 1, then the HWRM shall enable FEC autonegotiation + * on this port if supported. When enabled, at least one of the * FEC modes must be advertised by enabling the fec_clause_74_enable, * fec_clause_91_enable, fec_rs544_1xn_enable, fec_rs544_ieee_enable, - * fec_rs272_1xn_enable, or fec_rs272_ieee_enable flag. If none + * fec_rs272_1xn_enable, or fec_rs272_ieee_enable flag. If none * of the FEC mode is currently enabled, the HWRM shall choose * a default advertisement setting. * The default advertisement setting can be queried by calling - * hwrm_port_phy_qcfg. Note that the link speed must be + * hwrm_port_phy_qcfg. Note that the link speed must be * in autonegotiation mode for FEC autonegotiation to take effect. * When set to 0, then this flag shall be ignored. - * If FEC autonegotiation is not supported, then the HWRM shall ignore this - * flag. + * If FEC autonegotiation is not supported, then the HWRM shall + * ignore this flag. */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_ENABLE UINT32_C(0x100) /* * When set to 1, then the HWRM shall disable FEC autonegotiation - * on this port and use forced FEC mode. In forced FEC mode, one + * on this port and use forced FEC mode. In forced FEC mode, one * or more FEC forced settings under the same clause can be set. * When set to 0, then this flag shall be ignored. - * If FEC autonegotiation is not supported, then the HWRM shall ignore this - * flag. + * If FEC autonegotiation is not supported, then the HWRM shall + * ignore this flag. */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_DISABLE UINT32_C(0x200) /* - * When set to 1, then the HWRM shall enable FEC CLAUSE 74 (Fire Code) - * on this port if supported, by advertising FEC CLAUSE 74 if + * When set to 1, then the HWRM shall enable FEC CLAUSE 74 (Fire + * Code) on this port if supported, by advertising FEC CLAUSE 74 if * FEC autonegotiation is enabled or force enabled otherwise. * When set to 0, then this flag shall be ignored. * If FEC CLAUSE 74 is not supported, then the HWRM shall ignore this @@ -23827,9 +26693,9 @@ typedef struct hwrm_port_phy_cfg_input { */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE74_ENABLE UINT32_C(0x400) /* - * When set to 1, then the HWRM shall disable FEC CLAUSE 74 (Fire Code) - * on this port if supported, by not advertising FEC CLAUSE 74 if - * FEC autonegotiation is enabled or force disabled otherwise. + * When set to 1, then the HWRM shall disable FEC CLAUSE 74 (Fire + * Code) on this port if supported, by not advertising FEC CLAUSE 74 + * if FEC autonegotiation is enabled or force disabled otherwise. * When set to 0, then this flag shall be ignored. * If FEC CLAUSE 74 is not supported, then the HWRM shall ignore this * flag. @@ -23839,8 +26705,8 @@ typedef struct hwrm_port_phy_cfg_input { * When set to 1, then the HWRM shall enable FEC CLAUSE 91 * (Reed Solomon RS(528,514) for NRZ) on this port if supported, * by advertising FEC RS(528,514) if FEC autonegotiation is enabled - * or force enabled otherwise. In forced FEC mode, this flag - * will only take effect if the speed is NRZ. Additional + * or force enabled otherwise. In forced FEC mode, this flag + * will only take effect if the speed is NRZ. Additional * RS544 or RS272 flags (also under clause 91) may be set for PAM4 * in forced FEC mode. * When set to 0, then this flag shall be ignored. @@ -23852,8 +26718,8 @@ typedef struct hwrm_port_phy_cfg_input { * When set to 1, then the HWRM shall disable FEC CLAUSE 91 * (Reed Solomon RS(528,514) for NRZ) on this port if supported, by * not advertising RS(528,514) if FEC autonegotiation is enabled or - * force disabled otherwise. When set to 0, then this flag shall be - * ignored. If FEC RS(528,514) is not supported, then the HWRM + * force disabled otherwise. When set to 0, then this flag shall be + * ignored. If FEC RS(528,514) is not supported, then the HWRM * shall ignore this flag. */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE91_DISABLE UINT32_C(0x2000) @@ -23881,7 +26747,7 @@ typedef struct hwrm_port_phy_cfg_input { * on this port if supported, by advertising FEC RS544_1XN if * FEC autonegotiation is enabled or force enabled otherwise. * In forced mode, this flag will only take effect if the speed is - * PAM4. If this flag and fec_rs544_ieee_enable are set, the + * PAM4. If this flag and fec_rs544_ieee_enable are set, the * HWRM shall choose one of the RS544 modes. * When set to 0, then this flag shall be ignored. * If FEC RS544_1XN is not supported, then the HWRM shall ignore this @@ -23893,8 +26759,8 @@ typedef struct hwrm_port_phy_cfg_input { * on this port if supported, by not advertising FEC RS544_1XN if * FEC autonegotiation is enabled or force disabled otherwise. * When set to 0, then this flag shall be ignored. - * If FEC RS544_1XN is not supported, then the HWRM shall ignore this - * flag. + * If FEC RS544_1XN is not supported, then the HWRM shall ignore + * this flag. */ #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_RS544_1XN_DISABLE UINT32_C(0x10000) /* @@ -23902,7 +26768,7 @@ typedef struct hwrm_port_phy_cfg_input { * on this port if supported, by advertising FEC RS(544,514) if * FEC autonegotiation is enabled or force enabled otherwise. * In forced mode, this flag will only take effect if the speed is - * PAM4. If this flag and fec_rs544_1xn_enable are set, the + * PAM4. If this flag and fec_rs544_1xn_enable are set, the * HWRM shall choose one of the RS544 modes. * When set to 0, then this flag shall be ignored. * If FEC RS(544,514) is not supported, then the HWRM shall ignore @@ -23923,8 +26789,8 @@ typedef struct hwrm_port_phy_cfg_input { * on this port if supported, by advertising FEC RS272_1XN if * FEC autonegotiation is enabled or force enabled otherwise. * In forced mode, this flag will only take effect if the speed is - * PAM4. If this flag and fec_rs272_ieee_enable are set, the - * HWRM shall choose one of the RS272 modes. Note that RS272 + * PAM4. If this flag and fec_rs272_ieee_enable are set, the + * HWRM shall choose one of the RS272 modes. Note that RS272 * and RS544 modes cannot be set at the same time in forced FEC mode. * When set to 0, then this flag shall be ignored. * If FEC RS272_1XN is not supported, then the HWRM shall ignore this @@ -23945,8 +26811,8 @@ typedef struct hwrm_port_phy_cfg_input { * on this port if supported, by advertising FEC RS(272,257) if * FEC autonegotiation is enabled or force enabled otherwise. * In forced mode, this flag will only take effect if the speed is - * PAM4. If this flag and fec_rs272_1xn_enable are set, the - * HWRM shall choose one of the RS272 modes. Note that RS272 + * PAM4. If this flag and fec_rs272_1xn_enable are set, the + * HWRM shall choose one of the RS272 modes. Note that RS272 * and RS544 modes cannot be set at the same time in forced FEC mode. * When set to 0, then this flag shall be ignored. * If FEC RS(272,257) is not supported, then the HWRM shall ignore @@ -24028,11 +26894,21 @@ typedef struct hwrm_port_phy_cfg_input { * be configured. */ #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAM4_LINK_SPEED_MASK UINT32_C(0x1000) + /* + * This bit must be '1' for the force_link_speeds2 field to be + * configured. + */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_LINK_SPEEDS2 UINT32_C(0x2000) + /* + * This bit must be '1' for the auto_link_speeds2_mask field to + * be configured. + */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEEDS2_MASK UINT32_C(0x4000) /* Port ID of port that is to be configured. */ uint16_t port_id; /* * This is the speed that will be used if the force - * bit is '1'. If unsupported speed is selected, an error + * bit is '1'. If unsupported speed is selected, an error * will be generated. */ uint16_t force_link_speed; @@ -24069,18 +26945,19 @@ typedef struct hwrm_port_phy_cfg_input { /* Select all possible speeds for autoneg mode. */ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) /* - * Select only the auto_link_speed speed for autoneg mode. This mode has - * been DEPRECATED. An HWRM client should not use this mode. + * Select only the auto_link_speed speed for autoneg mode. This mode + * has been DEPRECATED. An HWRM client should not use this mode. */ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2) /* - * Select the auto_link_speed or any speed below that speed for autoneg. - * This mode has been DEPRECATED. An HWRM client should not use this mode. + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should not + * use this mode. */ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) /* - * Select the speeds based on the corresponding link speed mask values - * that are provided. The included speeds are specified in the + * Select the speeds based on the corresponding link speed mask + * values that are provided. The included speeds are specified in the * auto_link_speed and auto_pam4_link_speed fields. */ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK UINT32_C(0x4) @@ -24128,10 +27005,29 @@ typedef struct hwrm_port_phy_cfg_input { * 1, auto_pause bits should be ignored and should be set to 0. */ #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE UINT32_C(0x4) - uint8_t unused_0; + /* + * This field is only used by management firmware to communicate with + * core firmware regarding phy_port_cfg. + * It mainly used to notify core firmware that management firmware is + * using port for NCSI over RMII communication or not. + */ + uint8_t mgmt_flag; + /* + * Bit denoting if management firmware is using the link for + * NCSI over RMII communication. + * When set to 1, management firmware is no longer using the given + * port. + * When set to 0, management firmware is using the given port. + */ + #define HWRM_PORT_PHY_CFG_INPUT_MGMT_FLAG_LINK_RELEASE UINT32_C(0x1) + /* + * Validity bit, set to 1 to indicate other bits in mgmt_flags are + * valid. + */ + #define HWRM_PORT_PHY_CFG_INPUT_MGMT_FLAG_MGMT_VALID UINT32_C(0x80) /* * This is the speed that will be used if the autoneg_mode - * is "one_speed" or "one_or_below". If an unsupported speed + * is "one_speed" or "one_or_below". If an unsupported speed * is selected, an error will be generated. */ uint16_t auto_link_speed; @@ -24160,7 +27056,7 @@ typedef struct hwrm_port_phy_cfg_input { #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_LAST HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_10MB /* * This is a mask of link speeds that will be used if - * autoneg_mode is "mask". If unsupported speed is enabled + * autoneg_mode is "mask". If unsupported speed is enabled * an error will be generated. */ uint16_t auto_link_speed_mask; @@ -24201,7 +27097,7 @@ typedef struct hwrm_port_phy_cfg_input { #define HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_LAST HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_ON /* This value controls the loopback setting for the PHY. */ uint8_t lpbk; - /* No loopback is selected. Normal operation. */ + /* No loopback is selected. Normal operation. */ #define HWRM_PORT_PHY_CFG_INPUT_LPBK_NONE UINT32_C(0x0) /* * The HW will be configured with local loopback such that @@ -24217,7 +27113,8 @@ typedef struct hwrm_port_phy_cfg_input { /* * The HW will be configured with external loopback such that * host data is sent on the transmitter and based on the external - * loopback connection the data will be received without modification. + * loopback connection the data will be received without + * modification. */ #define HWRM_PORT_PHY_CFG_INPUT_LPBK_EXTERNAL UINT32_C(0x3) #define HWRM_PORT_PHY_CFG_INPUT_LPBK_LAST HWRM_PORT_PHY_CFG_INPUT_LPBK_EXTERNAL @@ -24239,7 +27136,7 @@ typedef struct hwrm_port_phy_cfg_input { uint8_t unused_1; /* * This value controls the pre-emphasis to be used for the - * link. Driver should not set this value (use + * link. Driver should not set this value (use * enable.preemphasis = 0) unless driver is sure of setting. * Normally HWRM FW will determine proper pre-emphasis. */ @@ -24270,7 +27167,7 @@ typedef struct hwrm_port_phy_cfg_input { #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40) /* * This is the speed that will be used if the force and force_pam4 - * bits are '1'. If unsupported speed is selected, an error + * bits are '1'. If unsupported speed is selected, an error * will be generated. */ uint16_t force_pam4_link_speed; @@ -24294,7 +27191,76 @@ typedef struct hwrm_port_phy_cfg_input { #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_PAM4_SPEED_MASK_50G UINT32_C(0x1) #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_PAM4_SPEED_MASK_100G UINT32_C(0x2) #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_PAM4_SPEED_MASK_200G UINT32_C(0x4) - uint8_t unused_2[2]; + /* + * This is the speed that will be used if the force_link_speeds2 + * bit is '1'. If unsupported speed is selected, an error + * will be generated. + */ + uint16_t force_link_speeds2; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_1GB UINT32_C(0xa) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_10GB UINT32_C(0x64) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_25GB UINT32_C(0xfa) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_40GB UINT32_C(0x190) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB UINT32_C(0x1f4) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB UINT32_C(0x3e8) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB_PAM4_56 UINT32_C(0x1f5) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_56 UINT32_C(0x3e9) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_56 UINT32_C(0x7d1) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_56 UINT32_C(0xfa1) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_112 UINT32_C(0x3ea) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_112 UINT32_C(0x7d2) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_112 UINT32_C(0xfa2) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_800GB_PAM4_112 UINT32_C(0x1f42) + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_LAST HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_800GB_PAM4_112 + /* + * This is a mask of link speeds that will be used if + * auto_link_speeds2_mask bit in the "enables" field is 1. + * If unsupported speed is enabled an error will be generated. + */ + uint16_t auto_link_speeds2_mask; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_1GB UINT32_C(0x1) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_10GB UINT32_C(0x2) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_25GB UINT32_C(0x4) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_40GB UINT32_C(0x8) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_50GB UINT32_C(0x10) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_100GB UINT32_C(0x20) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_50GB_PAM4_56 UINT32_C(0x40) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_100GB_PAM4_56 UINT32_C(0x80) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_200GB_PAM4_56 UINT32_C(0x100) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_400GB_PAM4_56 UINT32_C(0x200) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_100GB_PAM4_112 UINT32_C(0x400) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_200GB_PAM4_112 UINT32_C(0x800) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_400GB_PAM4_112 UINT32_C(0x1000) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEEDS2_MASK_800GB_PAM4_112 UINT32_C(0x2000) + uint8_t unused_2[6]; } hwrm_port_phy_cfg_input_t, *phwrm_port_phy_cfg_input_t; /* hwrm_port_phy_cfg_output (size:128b/16B) */ @@ -24311,9 +27277,9 @@ typedef struct hwrm_port_phy_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -24339,7 +27305,7 @@ typedef struct hwrm_port_phy_cfg_cmd_err { * but if a 0 is returned at any time then this should * be treated as an un recoverable failure, * - * retry interval in milli seconds is returned in opaque_1. + * retry interval in milliseconds is returned in opaque_1. * This specifies the time that user should wait before * issuing the next port_phy_cfg command. */ @@ -24418,9 +27384,11 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_SFT 0 /* NRZ signaling */ #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_NRZ UINT32_C(0x0) - /* PAM4 signaling */ + /* PAM4-56 signaling */ #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4 UINT32_C(0x1) - #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4 + /* PAM4-112 signaling */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4_112 UINT32_C(0x2) + #define HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4_112 /* This value indicates the current active FEC mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_MASK UINT32_C(0xf0) #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_SFT 4 @@ -24428,15 +27396,15 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_NONE_ACTIVE (UINT32_C(0x0) << 4) /* FEC CLAUSE 74 (Fire Code) active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_CLAUSE74_ACTIVE (UINT32_C(0x1) << 4) - /* FEC CLAUSE 91 RS(528,514) active, autonegoatiated or forced. */ + /* FEC CLAUSE 91 RS(528,514) active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_CLAUSE91_ACTIVE (UINT32_C(0x2) << 4) - /* FEC RS544_1XN active, autonegoatiated or forced. */ + /* FEC RS544_1XN active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_RS544_1XN_ACTIVE (UINT32_C(0x3) << 4) - /* FEC RS(544,528) active, autonegoatiated or forced. */ + /* FEC RS(544,528) active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_RS544_IEEE_ACTIVE (UINT32_C(0x4) << 4) /* FEC RS272_1XN active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_RS272_1XN_ACTIVE (UINT32_C(0x5) << 4) - /* FEC RS(272,257) active, autonegoatiated or forced. */ + /* FEC RS(272,257) active, autonegotiated or forced. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE (UINT32_C(0x6) << 4) #define HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_LAST HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE /* @@ -24467,6 +27435,10 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB UINT32_C(0x3e8) /* 200Gb link speed */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB UINT32_C(0x7d0) + /* 400Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_400GB UINT32_C(0xfa0) + /* 800Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_800GB UINT32_C(0x1f40) /* 10Mb link speed */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB UINT32_C(0xffff) #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_LAST HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB @@ -24566,13 +27538,14 @@ typedef struct hwrm_port_phy_qcfg_output { /* Select all possible speeds for autoneg mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) /* - * Select only the auto_link_speed speed for autoneg mode. This mode has - * been DEPRECATED. An HWRM client should not use this mode. + * Select only the auto_link_speed speed for autoneg mode. This mode + * has been DEPRECATED. An HWRM client should not use this mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2) /* - * Select the auto_link_speed or any speed below that speed for autoneg. - * This mode has been DEPRECATED. An HWRM client should not use this mode. + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should not + * use this mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) /* @@ -24684,7 +27657,7 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_LAST HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_ON /* Current setting for loopback. */ uint8_t lpbk; - /* No loopback is selected. Normal operation. */ + /* No loopback is selected. Normal operation. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0) /* * The HW will be configured with local loopback such that @@ -24700,7 +27673,8 @@ typedef struct hwrm_port_phy_qcfg_output { /* * The HW will be configured with external loopback such that * host data is sent on the transmitter and based on the external - * loopback connection the data will be received without modification. + * loopback connection the data will be received without + * modification. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_EXTERNAL UINT32_C(0x3) #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_LAST HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_EXTERNAL @@ -24737,6 +27711,8 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTINSERTED UINT32_C(0x4) /* Module is powered down because of over current fault. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_CURRENTFAULT UINT32_C(0x5) + /* Module is overheated. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_OVERHEATED UINT32_C(0x6) /* Module status is not applicable. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTAPPLICABLE UINT32_C(0xff) #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_LAST HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTAPPLICABLE @@ -24830,7 +27806,51 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR2 UINT32_C(0x26) /* 100G_BASEER2 */ #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER2 UINT32_C(0x27) - #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER2 + /* 400G_BASECR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR UINT32_C(0x28) + /* 100G_BASESR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR UINT32_C(0x29) + /* 100G_BASELR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR UINT32_C(0x2a) + /* 100G_BASEER */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER UINT32_C(0x2b) + /* 200G_BASECR2 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASECR2 UINT32_C(0x2c) + /* 200G_BASESR2 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASESR2 UINT32_C(0x2d) + /* 200G_BASELR2 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASELR2 UINT32_C(0x2e) + /* 200G_BASEER2 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASEER2 UINT32_C(0x2f) + /* 400G_BASECR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASECR8 UINT32_C(0x30) + /* 200G_BASESR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASESR8 UINT32_C(0x31) + /* 400G_BASELR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASELR8 UINT32_C(0x32) + /* 400G_BASEER8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASEER8 UINT32_C(0x33) + /* 400G_BASECR4 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASECR4 UINT32_C(0x34) + /* 400G_BASESR4 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASESR4 UINT32_C(0x35) + /* 400G_BASELR4 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASELR4 UINT32_C(0x36) + /* 400G_BASEER4 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASEER4 UINT32_C(0x37) + /* 800G_BASECR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASECR8 UINT32_C(0x38) + /* 800G_BASESR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASESR8 UINT32_C(0x39) + /* 800G_BASELR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASELR8 UINT32_C(0x3a) + /* 800G_BASEER8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASEER8 UINT32_C(0x3b) + /* 800G_BASEFR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASEFR8 UINT32_C(0x3c) + /* 800G_BASEDR8 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASEDR8 UINT32_C(0x3d) + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_800G_BASEDR8 /* This value represents a media type. */ uint8_t media_type; /* Unknown */ @@ -24862,9 +27882,9 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_MASK UINT32_C(0xe0) #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_SFT 5 /* - * When set to 1, Energy Efficient Ethernet (EEE) mode is enabled. - * Speeds for autoneg with EEE mode enabled - * are based on eee_link_speed_mask. + * When set to 1, Energy Efficient Ethernet (EEE) mode is + * enabled. Speeds for autoneg with EEE mode enabled are based on + * eee_link_speed_mask. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_ENABLED UINT32_C(0x20) /* @@ -24954,13 +27974,14 @@ typedef struct hwrm_port_phy_qcfg_output { /* Select all possible speeds for autoneg mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) /* - * Select only the auto_link_speed speed for autoneg mode. This mode has - * been DEPRECATED. An HWRM client should not use this mode. + * Select only the auto_link_speed speed for autoneg mode. This mode + * has been DEPRECATED. An HWRM client should not use this mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED UINT32_C(0x2) /* - * Select the auto_link_speed or any speed below that speed for autoneg. - * This mode has been DEPRECATED. An HWRM client should not use this mode. + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should not + * use this mode. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) /* @@ -25042,43 +28063,55 @@ typedef struct hwrm_port_phy_qcfg_output { #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP (UINT32_C(0xc) << 24) /* QSFP+ */ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPPLUS (UINT32_C(0xd) << 24) - /* QSFP28 */ + /* QSFP28/QSFP56 or later */ #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28 (UINT32_C(0x11) << 24) - #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28 + /* QSFP-DD */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPDD (UINT32_C(0x18) << 24) + /* QSFP112 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP112 (UINT32_C(0x1e) << 24) + /* SFP-DD CMIS */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFPDD (UINT32_C(0x1f) << 24) + /* SFP CMIS */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_CSFP (UINT32_C(0x20) << 24) + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_LAST HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_CSFP /* * This value represents the current configuration of * Forward Error Correction (FEC) on the port. */ uint16_t fec_cfg; /* - * When set to 1, then FEC is not supported on this port. If this flag - * is set to 1, then all other FEC configuration flags shall be ignored. - * When set to 0, then FEC is supported as indicated by other - * configuration flags. + * When set to 1, then FEC is not supported on this port. If this + * flag is set to 1, then all other FEC configuration flags shall be + * ignored. When set to 0, then FEC is supported as indicated by + * other configuration flags. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_NONE_SUPPORTED UINT32_C(0x1) /* * When set to 1, then FEC autonegotiation is supported on this port. - * When set to 0, then FEC autonegotiation is not supported on this port. + * When set to 0, then FEC autonegotiation is not supported on this + * port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_SUPPORTED UINT32_C(0x2) /* * When set to 1, then FEC autonegotiation is enabled on this port. * When set to 0, then FEC autonegotiation is disabled if supported. - * This flag should be ignored if FEC autonegotiation is not supported on this port. + * This flag should be ignored if FEC autonegotiation is not + * supported on this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_ENABLED UINT32_C(0x4) /* - * When set to 1, then FEC CLAUSE 74 (Fire Code) is supported on this port. - * When set to 0, then FEC CLAUSE 74 (Fire Code) is not supported on this port. + * When set to 1, then FEC CLAUSE 74 (Fire Code) is supported on this + * port. When set to 0, then FEC CLAUSE 74 (Fire Code) is not + * supported on this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_SUPPORTED UINT32_C(0x8) /* * When set to 1, then FEC CLAUSE 74 (Fire Code) is enabled on this * port. This means that FEC CLAUSE 74 is either advertised if * FEC autonegotiation is enabled or FEC CLAUSE 74 is force enabled. - * When set to 0, then FEC CLAUSE 74 (Fire Code) is disabled if supported. - * This flag should be ignored if FEC CLAUSE 74 is not supported on this port. + * When set to 0, then FEC CLAUSE 74 (Fire Code) is disabled if + * supported. This flag should be ignored if FEC CLAUSE 74 is not + * supported on this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_ENABLED UINT32_C(0x10) /* @@ -25091,9 +28124,10 @@ typedef struct hwrm_port_phy_qcfg_output { * When set to 1, then FEC CLAUSE 91 (Reed Solomon RS(528,514) for * NRZ) is enabled on this port. This means that FEC RS(528,514) is * either advertised if FEC autonegotiation is enabled or FEC - * RS(528,514) is force enabled. When set to 0, then FEC RS(528,514) + * RS(528,514) is force enabled. When set to 0, then FEC RS(528,514) * is disabled if supported. - * This flag should be ignored if FEC CLAUSE 91 is not supported on this port. + * This flag should be ignored if FEC CLAUSE 91 is not supported on + * this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE91_ENABLED UINT32_C(0x40) /* @@ -25106,7 +28140,8 @@ typedef struct hwrm_port_phy_qcfg_output { * port. This means that FEC RS544_1XN is either advertised if * FEC autonegotiation is enabled or FEC RS544_1XN is force enabled. * When set to 0, then FEC RS544_1XN is disabled if supported. - * This flag should be ignored if FEC RS544_1XN is not supported on this port. + * This flag should be ignored if FEC RS544_1XN is not supported on + * this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_RS544_1XN_ENABLED UINT32_C(0x100) /* @@ -25118,8 +28153,9 @@ typedef struct hwrm_port_phy_qcfg_output { * When set to 1, then RS(544,514) is enabled on this * port. This means that FEC RS(544,514) is either advertised if * FEC autonegotiation is enabled or FEC RS(544,514) is force - * enabled. When set to 0, then FEC RS(544,514) is disabled if supported. - * This flag should be ignored if FEC RS(544,514) is not supported on this port. + * enabled. When set to 0, then FEC RS(544,514) is disabled if + * supported. This flag should be ignored if FEC RS(544,514) is not + * supported on this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_RS544_IEEE_ENABLED UINT32_C(0x400) /* @@ -25131,8 +28167,10 @@ typedef struct hwrm_port_phy_qcfg_output { * When set to 1, then RS272_1XN is enabled on this * port. This means that FEC RS272_1XN is either advertised if * FEC autonegotiation is enabled or FEC RS272_1XN is force - * enabled. When set to 0, then FEC RS272_1XN is disabled if supported. - * This flag should be ignored if FEC RS272_1XN is not supported on this port. + * enabled. When set to 0, then FEC RS272_1XN is disabled if + * supported. + * This flag should be ignored if FEC RS272_1XN is not supported on + * this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_RS272_1XN_ENABLED UINT32_C(0x1000) /* @@ -25144,8 +28182,10 @@ typedef struct hwrm_port_phy_qcfg_output { * When set to 1, then RS(272,257) is enabled on this * port. This means that FEC RS(272,257) is either advertised if * FEC autonegotiation is enabled or FEC RS(272,257) is force - * enabled. When set to 0, then FEC RS(272,257) is disabled if supported. - * This flag should be ignored if FEC RS(272,257) is not supported on this port. + * enabled. When set to 0, then FEC RS(272,257) is disabled if + * supported. + * This flag should be ignored if FEC RS(272,257) is not supported on + * this port. */ #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_RS272_IEEE_ENABLED UINT32_C(0x4000) /* @@ -25168,6 +28208,11 @@ typedef struct hwrm_port_phy_qcfg_output { */ #define HWRM_PORT_PHY_QCFG_OUTPUT_OPTION_FLAGS_SIGNAL_MODE_KNOWN UINT32_C(0x2) /* + * When this bit is '1', speeds2 fields are used to get + * speed details. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_OPTION_FLAGS_SPEEDS2_SUPPORTED UINT32_C(0x4) + /* * Up to 16 bytes of null padded ASCII string representing * PHY vendor. * If the string is set to null, then the vendor name is not @@ -25232,12 +28277,125 @@ typedef struct hwrm_port_phy_qcfg_output { uint8_t link_down_reason; /* Remote fault */ #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_DOWN_REASON_RF UINT32_C(0x1) - uint8_t unused_0[7]; + /* + * The supported speeds for the port. This is a bit mask. + * For each speed that is supported, the corresponding + * bit will be set to '1'. This is valid only if speeds2_supported + * is set in option_flags + */ + uint16_t support_speeds2; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_1GB UINT32_C(0x1) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_10GB UINT32_C(0x2) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_25GB UINT32_C(0x4) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_40GB UINT32_C(0x8) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB UINT32_C(0x10) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB UINT32_C(0x20) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB_PAM4_56 UINT32_C(0x40) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_56 UINT32_C(0x80) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_56 UINT32_C(0x100) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_56 UINT32_C(0x200) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_112 UINT32_C(0x400) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_112 UINT32_C(0x800) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_112 UINT32_C(0x1000) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_800GB_PAM4_112 UINT32_C(0x2000) + /* + * Current setting of forced link speed. When the link speed is not + * being forced, this value shall be set to 0. + * This field is valid only if speeds2_supported is set in + * option_flags. + */ + uint16_t force_link_speeds2; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_1GB UINT32_C(0xa) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_10GB UINT32_C(0x64) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_25GB UINT32_C(0xfa) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_40GB UINT32_C(0x190) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_50GB UINT32_C(0x1f4) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_100GB UINT32_C(0x3e8) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_50GB_PAM4_56 UINT32_C(0x1f5) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_56 UINT32_C(0x3e9) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_56 UINT32_C(0x7d1) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_56 UINT32_C(0xfa1) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_112 UINT32_C(0x3ea) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_112 UINT32_C(0x7d2) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_112 UINT32_C(0xfa2) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_800GB_PAM4_112 UINT32_C(0x1f42) + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_LAST HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEEDS2_800GB_PAM4_112 + /* + * Current setting of auto_link speed_mask that is used to advertise + * speeds during autonegotiation. + * This field is only valid when auto_mode is set to "mask". + * and if speeds2_supported is set in option_flags + * The speeds specified in this field shall be a subset of + * supported speeds on this port. + */ + uint16_t auto_link_speeds2; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_1GB UINT32_C(0x1) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_10GB UINT32_C(0x2) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_25GB UINT32_C(0x4) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_40GB UINT32_C(0x8) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_50GB UINT32_C(0x10) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_100GB UINT32_C(0x20) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_50GB_PAM4_56 UINT32_C(0x40) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_100GB_PAM4_56 UINT32_C(0x80) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_200GB_PAM4_56 UINT32_C(0x100) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_400GB_PAM4_56 UINT32_C(0x200) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_100GB_PAM4_112 UINT32_C(0x400) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_200GB_PAM4_112 UINT32_C(0x800) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_400GB_PAM4_112 UINT32_C(0x1000) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEEDS2_800GB_PAM4_112 UINT32_C(0x2000) + /* + * This field is indicate the number of lanes used to transfer + * data. If the link is down, the value is zero. + * This is valid only if speeds2_supported is set in option_flags. + */ + uint8_t active_lanes; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -25420,13 +28578,13 @@ typedef struct hwrm_port_mac_cfg_input { */ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_DSCP2COS_MAP_PRI UINT32_C(0x20) /* - * This bit must be '1' for the rx_ts_capture_ptp_msg_type field to be - * configured. + * This bit must be '1' for the rx_ts_capture_ptp_msg_type field to + * be configured. */ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x40) /* - * This bit must be '1' for the tx_ts_capture_ptp_msg_type field to be - * configured. + * This bit must be '1' for the tx_ts_capture_ptp_msg_type field to + * be configured. */ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_TX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x80) /* @@ -25444,6 +28602,11 @@ typedef struct hwrm_port_mac_cfg_input { * configured. */ #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_PTP_ADJ_PHASE UINT32_C(0x400) + /* + * This bit must be '1' for the ptp_load_control field to + * be configured. + */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_PTP_LOAD_CONTROL UINT32_C(0x800) /* Port ID of port that is to be configured. */ uint16_t port_id; /* @@ -25453,7 +28616,7 @@ typedef struct hwrm_port_mac_cfg_input { uint8_t ipg; /* This value controls the loopback setting for the MAC. */ uint8_t lpbk; - /* No loopback is selected. Normal operation. */ + /* No loopback is selected. Normal operation. */ #define HWRM_PORT_MAC_CFG_INPUT_LPBK_NONE UINT32_C(0x0) /* * The HW will be configured with local loopback such that @@ -25618,7 +28781,25 @@ typedef struct hwrm_port_mac_cfg_input { * of sync timer updates (measured in parts per billion). */ int32_t ptp_freq_adj_ppb; - uint8_t unused_1[4]; + uint8_t unused_1[3]; + /* + * This value controls how PTP configuration like freq_adj and + * phase are loaded in the hardware block. + */ + uint8_t ptp_load_control; + /* PTP configuration is not loaded in hardware. */ + #define HWRM_PORT_MAC_CFG_INPUT_PTP_LOAD_CONTROL_NONE UINT32_C(0x0) + /* + * PTP configuration will be loaded immediately in the hardware + * block. By default, it will always be immediate. + */ + #define HWRM_PORT_MAC_CFG_INPUT_PTP_LOAD_CONTROL_IMMEDIATE UINT32_C(0x1) + /* + * PTP configuration will loaded at the next Pulse per second (PPS) + * event in the hardware block. + */ + #define HWRM_PORT_MAC_CFG_INPUT_PTP_LOAD_CONTROL_PPS_EVENT UINT32_C(0x2) + #define HWRM_PORT_MAC_CFG_INPUT_PTP_LOAD_CONTROL_LAST HWRM_PORT_MAC_CFG_INPUT_PTP_LOAD_CONTROL_PPS_EVENT /* * This unsigned field specifies the phase offset to be applied * to the PHC (PTP Hardware Clock). This field is specified in @@ -25656,7 +28837,7 @@ typedef struct hwrm_port_mac_cfg_output { uint8_t ipg; /* Current value of the loopback value. */ uint8_t lpbk; - /* No loopback is selected. Normal operation. */ + /* No loopback is selected. Normal operation. */ #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_NONE UINT32_C(0x0) /* * The HW will be configured with local loopback such that @@ -25673,9 +28854,9 @@ typedef struct hwrm_port_mac_cfg_output { uint8_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -25754,7 +28935,7 @@ typedef struct hwrm_port_mac_qcfg_output { uint8_t ipg; /* The loopback setting for the MAC. */ uint8_t lpbk; - /* No loopback is selected. Normal operation. */ + /* No loopback is selected. Normal operation. */ #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0) /* * The HW will be configured with local loopback such that @@ -25942,20 +29123,35 @@ typedef struct hwrm_port_mac_qcfg_output { uint8_t unused_1; uint16_t port_svif_info; /* - * This field specifies the source virtual interface of the port being - * queried. Drivers can use this to program port svif field in the - * L2 context table + * This field specifies the source virtual interface of the port + * being queried. Drivers can use this to program port svif field in + * the L2 context table. */ #define HWRM_PORT_MAC_QCFG_OUTPUT_PORT_SVIF_INFO_PORT_SVIF_MASK UINT32_C(0x7fff) #define HWRM_PORT_MAC_QCFG_OUTPUT_PORT_SVIF_INFO_PORT_SVIF_SFT 0 /* This field specifies whether port_svif is valid or not */ #define HWRM_PORT_MAC_QCFG_OUTPUT_PORT_SVIF_INFO_PORT_SVIF_VALID UINT32_C(0x8000) - uint8_t unused_2[5]; + /* + * This field indicates the configured load control for PTP + * time of day (TOD) block. + */ + uint8_t ptp_load_control; + /* Indicates the current load control is none. */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_PTP_LOAD_CONTROL_NONE UINT32_C(0x0) + /* Indicates the current load control is immediate. */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_PTP_LOAD_CONTROL_IMMEDIATE UINT32_C(0x1) + /* + * Indicates current load control is at next Pulse per Second (PPS) + * event. + */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_PTP_LOAD_CONTROL_PPS_EVENT UINT32_C(0x2) + #define HWRM_PORT_MAC_QCFG_OUTPUT_PTP_LOAD_CONTROL_LAST HWRM_PORT_MAC_QCFG_OUTPUT_PTP_LOAD_CONTROL_PPS_EVENT + uint8_t unused_2[4]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -26044,6 +29240,11 @@ typedef struct hwrm_port_mac_ptp_qcfg_output { * configured 64bit RTC. */ #define HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_RTC_CONFIGURED UINT32_C(0x20) + /* + * When this bit is set to '1', it indicates that current time + * exposed to driver is 64bit. + */ + #define HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_64B_PHC_TIME UINT32_C(0x40) uint8_t unused_0[3]; /* * Offset of the PTP register for the lower 32 bits of timestamp @@ -26094,9 +29295,9 @@ typedef struct hwrm_port_mac_ptp_qcfg_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -26536,9 +29737,9 @@ typedef struct hwrm_port_qstats_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -26580,42 +29781,90 @@ typedef struct tx_port_stats_ext { uint64_t tx_packets_cos6; /* Total number of tx packets count on cos queue 7 */ uint64_t tx_packets_cos7; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 0 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 0 + */ uint64_t pfc_pri0_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 0 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 0 + */ uint64_t pfc_pri0_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 1 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 1 + */ uint64_t pfc_pri1_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 1 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 1 + */ uint64_t pfc_pri1_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 2 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 2 + */ uint64_t pfc_pri2_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 2 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 2 + */ uint64_t pfc_pri2_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 3 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 3 + */ uint64_t pfc_pri3_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 3 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 3 + */ uint64_t pfc_pri3_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 4 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 4 + */ uint64_t pfc_pri4_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 4 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 4 + */ uint64_t pfc_pri4_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 5 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 5 + */ uint64_t pfc_pri5_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 5 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 5 + */ uint64_t pfc_pri5_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 6 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 6 + */ uint64_t pfc_pri6_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 6 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 6 + */ uint64_t pfc_pri6_tx_transitions; - /* time duration between transmitting a XON -> XOFF and a subsequent XOFF -> XON for priority 7 */ + /* + * time duration between transmitting a XON -> XOFF and a subsequent XOFF + * -> XON for priority 7 + */ uint64_t pfc_pri7_tx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 7 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 7 + */ uint64_t pfc_pri7_tx_transitions; } tx_port_stats_ext_t, *ptx_port_stats_ext_t; /* Port Rx Statistics extended Format */ -/* rx_port_stats_ext (size:3776b/472B) */ +/* rx_port_stats_ext (size:3904b/488B) */ typedef struct rx_port_stats_ext { /* Number of times link state changed to down */ @@ -26624,7 +29873,10 @@ typedef struct rx_port_stats_ext { uint64_t continuous_pause_events; /* Number of times the active rings pause bit resumed back */ uint64_t resume_pause_events; - /* Number of times, the ROCE cos queue PFC is disabled to avoid pause flood/burst */ + /* + * Number of times, the ROCE cos queue PFC is disabled to avoid pause + * flood/burst + */ uint64_t continuous_roce_pause_events; /* Number of times, the ROCE cos queue PFC is enabled back */ uint64_t resume_roce_pause_events; @@ -26660,45 +29912,94 @@ typedef struct rx_port_stats_ext { uint64_t rx_packets_cos6; /* Total number of rx packets count on cos queue 7 */ uint64_t rx_packets_cos7; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 0 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 0 + */ uint64_t pfc_pri0_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 0 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 0 + */ uint64_t pfc_pri0_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 1 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 1 + */ uint64_t pfc_pri1_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 1 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 1 + */ uint64_t pfc_pri1_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 2 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 2 + */ uint64_t pfc_pri2_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 2 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 2 + */ uint64_t pfc_pri2_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 3 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 3 + */ uint64_t pfc_pri3_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 3 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 3 + */ uint64_t pfc_pri3_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 4 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 4 + */ uint64_t pfc_pri4_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 4 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 4 + */ uint64_t pfc_pri4_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 5 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 5 + */ uint64_t pfc_pri5_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 5 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 5 + */ uint64_t pfc_pri5_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 6 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 6 + */ uint64_t pfc_pri6_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 6 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 6 + */ uint64_t pfc_pri6_rx_transitions; - /* time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for priority 7 */ + /* + * time duration receiving a XON -> XOFF and a subsequent XOFF -> XON for + * priority 7 + */ uint64_t pfc_pri7_rx_duration_us; - /* Number of times, a XON -> XOFF and XOFF -> XON transitions occur for priority 7 */ + /* + * Number of times, a XON -> XOFF and XOFF -> XON transitions occur for + * priority 7 + */ uint64_t pfc_pri7_rx_transitions; /* Total number of received bits */ uint64_t rx_bits; /* The number of events where the port receive buffer was over 85% full */ uint64_t rx_buffer_passed_threshold; /* - * The number of symbol errors that wasn't corrected by FEC correction - * algorithm + * This counter represents uncorrected symbol errors post-FEC and may not + * be populated in all cases. Each uncorrected FEC block may result in + * one or more symbol errors. */ uint64_t rx_pcs_symbol_err; /* The number of corrected bits on the port according to active FEC */ @@ -26742,6 +30043,21 @@ typedef struct rx_port_stats_ext { * FEC function in the PHY */ uint64_t rx_fec_uncorrectable_blocks; + /* + * Total number of packets that are dropped due to not matching + * any RX filter rules. This value is zero on the non supported + * controllers. This counter is per controller, Firmware reports the + * same value on active ports. This counter does not include the + * packet discards because of no available buffers. + */ + uint64_t rx_filter_miss; + /* + * This field represents the number of FEC symbol errors by counting + * once for each 10-bit symbol corrected by FEC block. + * rx_fec_corrected_blocks will be incremented if all symbol errors in a + * codeword gets corrected. + */ + uint64_t rx_fec_symbol_err; } rx_port_stats_ext_t, *prx_port_stats_ext_t; /* @@ -27256,9 +30572,9 @@ typedef struct hwrm_port_qstats_ext_output { #define HWRM_PORT_QSTATS_EXT_OUTPUT_FLAGS_CLEAR_ROCE_COUNTERS_SUPPORTED UINT32_C(0x1) /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -27331,16 +30647,15 @@ typedef struct hwrm_port_qstats_ext_pfc_wd_output { * statistics block in bytes. */ uint16_t pfc_wd_stat_size; - uint8_t flags; + uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; - uint8_t unused_0[4]; } hwrm_port_qstats_ext_pfc_wd_output_t, *phwrm_port_qstats_ext_pfc_wd_output_t; /************************* @@ -27348,7 +30663,7 @@ typedef struct hwrm_port_qstats_ext_pfc_wd_output { *************************/ -/* hwrm_port_lpbk_qstats_input (size:128b/16B) */ +/* hwrm_port_lpbk_qstats_input (size:256b/32B) */ typedef struct hwrm_port_lpbk_qstats_input { /* The HWRM command request type. */ @@ -27379,9 +30694,30 @@ typedef struct hwrm_port_lpbk_qstats_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * The size of the loopback statistics buffer passed in the + * loopback_stat_host_addr in bytes. + * Firmware will not exceed this size when it DMAs the + * statistics structure to the host. The actual DMA size + * will be returned in the response. + */ + uint16_t lpbk_stat_size; + uint8_t flags; + /* + * This bit is set to 1 when request is for a counter mask, + * representing the width of each of the stats counters, rather + * than counters themselves. + */ + #define HWRM_PORT_LPBK_QSTATS_INPUT_FLAGS_COUNTER_MASK UINT32_C(0x1) + uint8_t unused_0[5]; + /* + * This is the host address where + * loopback statistics will be stored + */ + uint64_t lpbk_stat_host_addr; } hwrm_port_lpbk_qstats_input_t, *phwrm_port_lpbk_qstats_input_t; -/* hwrm_port_lpbk_qstats_output (size:768b/96B) */ +/* hwrm_port_lpbk_qstats_output (size:128b/16B) */ typedef struct hwrm_port_lpbk_qstats_output { /* The specific error status for the command. */ @@ -27392,6 +30728,29 @@ typedef struct hwrm_port_lpbk_qstats_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; + /* + * The size of the loopback statistics block in bytes DMA'ed by the + * firmware. Note that this size will never exceed the lpbk_stat_size + * field passed in by the driver in the hwrm_port_lpbk_qstats_input + * structure. + */ + uint16_t lpbk_stat_size; + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field is + * written last. + */ + uint8_t valid; +} hwrm_port_lpbk_qstats_output_t, *phwrm_port_lpbk_qstats_output_t; + +/* Loopback Port Statistic Format */ +/* port_lpbk_stats (size:640b/80B) */ + +typedef struct port_lpbk_stats { /* Number of transmitted unicast frames */ uint64_t lpbk_ucast_frames; /* Number of transmitted multicast frames */ @@ -27404,24 +30763,15 @@ typedef struct hwrm_port_lpbk_qstats_output { uint64_t lpbk_mcast_bytes; /* Number of transmitted bytes for broadcast traffic */ uint64_t lpbk_bcast_bytes; - /* Total Tx Drops for loopback traffic reported by STATS block */ - uint64_t tx_stat_discard; - /* Total Tx Error Drops for loopback traffic reported by STATS block */ - uint64_t tx_stat_error; - /* Total Rx Drops for loopback traffic reported by STATS block */ - uint64_t rx_stat_discard; - /* Total Rx Error Drops for loopback traffic reported by STATS block */ - uint64_t rx_stat_error; - uint8_t unused_0[7]; - /* - * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, - * the order of writes has to be such that this field is written last. - */ - uint8_t valid; -} hwrm_port_lpbk_qstats_output_t, *phwrm_port_lpbk_qstats_output_t; + /* Number of dropped tx packets */ + uint64_t lpbk_tx_discards; + /* Number of error dropped tx packets */ + uint64_t lpbk_tx_errors; + /* Number of dropped rx packets */ + uint64_t lpbk_rx_discards; + /* Number of error dropped rx packets */ + uint64_t lpbk_rx_errors; +} port_lpbk_stats_t, *pport_lpbk_stats_t; /************************ * hwrm_port_ecn_qstats * @@ -27505,9 +30855,9 @@ typedef struct hwrm_port_ecn_qstats_output { uint8_t unused_0[4]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -27612,7 +30962,8 @@ typedef struct hwrm_port_clr_stats_input { * RoCE associated TX/RX cos counters * CNP associated TX/RX cos counters * RoCE/CNP specific TX/RX flow counters - * Firmware will determine the RoCE/CNP cos queue based on qos profile. + * Firmware will determine the RoCE/CNP cos queue based on qos + * profile. * This flag is honored only when RoCE is enabled on that port. */ #define HWRM_PORT_CLR_STATS_INPUT_FLAGS_ROCE_COUNTERS UINT32_C(0x1) @@ -27633,9 +30984,9 @@ typedef struct hwrm_port_clr_stats_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -27646,7 +30997,7 @@ typedef struct hwrm_port_clr_stats_output { ****************************/ -/* hwrm_port_lpbk_clr_stats_input (size:128b/16B) */ +/* hwrm_port_lpbk_clr_stats_input (size:192b/24B) */ typedef struct hwrm_port_lpbk_clr_stats_input { /* The HWRM command request type. */ @@ -27677,6 +31028,9 @@ typedef struct hwrm_port_lpbk_clr_stats_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* Port ID of port that is to be queried. */ + uint16_t port_id; + uint8_t unused_0[6]; } hwrm_port_lpbk_clr_stats_input_t, *phwrm_port_lpbk_clr_stats_input_t; /* hwrm_port_lpbk_clr_stats_output (size:128b/16B) */ @@ -27693,9 +31047,9 @@ typedef struct hwrm_port_lpbk_clr_stats_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -27819,9 +31173,9 @@ typedef struct hwrm_port_ts_query_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -27868,7 +31222,7 @@ typedef struct hwrm_port_phy_qcaps_input { uint8_t unused_0[6]; } hwrm_port_phy_qcaps_input_t, *phwrm_port_phy_qcaps_input_t; -/* hwrm_port_phy_qcaps_output (size:256b/32B) */ +/* hwrm_port_phy_qcaps_output (size:320b/40B) */ typedef struct hwrm_port_phy_qcaps_output { /* The specific error status for the command. */ @@ -27897,9 +31251,9 @@ typedef struct hwrm_port_phy_qcaps_output { */ #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_AUTONEG_LPBK_SUPPORTED UINT32_C(0x4) /* - * Indicates if the configuration of shared PHY settings is supported. - * In cases where a physical port is shared by multiple functions - * (e.g. NPAR, multihost, etc), the configuration of PHY + * Indicates if the configuration of shared PHY settings is + * supported. In cases where a physical port is shared by multiple + * functions (e.g. NPAR, multihost, etc), the configuration of PHY * settings may not be allowed. Callers to HWRM_PORT_PHY_CFG will * get an HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED error in this case. */ @@ -27907,7 +31261,7 @@ typedef struct hwrm_port_phy_qcaps_output { /* * If set to 1, it indicates that the port counters and extended * port counters will not reset when the firmware shuts down or - * resets the PHY. These counters will only be reset during power + * resets the PHY. These counters will only be reset during power * cycle or by calling HWRM_PORT_CLR_STATS. * If set to 0, the state of the counters is unspecified when * firmware shuts down or resets the PHY. @@ -28096,13 +31450,24 @@ typedef struct hwrm_port_phy_qcaps_output { * If set to 1, then this field indicates that * priority-based flow control is not supported. */ - #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED UINT32_C(0x2) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED UINT32_C(0x2) /* * If set to 1, then this field indicates that * bank based addressing is supported in firmware. */ #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_BANK_ADDR_SUPPORTED UINT32_C(0x4) /* + * If set to 1, then this field indicates that + * supported_speed2 field is to be used in lieu of all + * supported_speed variants. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_SPEEDS2_SUPPORTED UINT32_C(0x8) + /* + * If set to 1, then this field indicates that + * the device does not support remote loopback. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_REMOTE_LPBK_UNSUPPORTED UINT32_C(0x10) + /* * Number of internal ports for this device. This field allows the FW * to advertise how many internal ports are present. Manufacturing * tools uses this to determine how many internal ports should have @@ -28110,11 +31475,85 @@ typedef struct hwrm_port_phy_qcaps_output { * option "HPTN_MODE" is set to 1. */ uint8_t internal_port_cnt; + uint8_t unused_0; + /* + * This is a bit mask to indicate what speeds are supported + * as forced speeds on this link. + * For each speed that can be forced on this link, the + * corresponding mask bit shall be set to '1'. + * This field is valid only if speeds2_supported bit is set in flags2 + */ + uint16_t supported_speeds2_force_mode; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_1GB UINT32_C(0x1) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_10GB UINT32_C(0x2) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_25GB UINT32_C(0x4) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_40GB UINT32_C(0x8) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_50GB UINT32_C(0x10) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_100GB UINT32_C(0x20) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_50GB_PAM4_56 UINT32_C(0x40) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_100GB_PAM4_56 UINT32_C(0x80) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_200GB_PAM4_56 UINT32_C(0x100) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_400GB_PAM4_56 UINT32_C(0x200) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_100GB_PAM4_112 UINT32_C(0x400) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_200GB_PAM4_112 UINT32_C(0x800) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_400GB_PAM4_112 UINT32_C(0x1000) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_FORCE_MODE_800GB_PAM4_112 UINT32_C(0x2000) + /* + * This is a bit mask to indicate what speeds are supported + * for autonegotiation on this link. + * For each speed that can be autonegotiated on this link, the + * corresponding mask bit shall be set to '1'. + * This field is valid only if speeds2_supported bit is set in flags2 + */ + uint16_t supported_speeds2_auto_mode; + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_1GB UINT32_C(0x1) + /* 10Gb (NRZ: 10G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_10GB UINT32_C(0x2) + /* 25Gb (NRZ: 25G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_25GB UINT32_C(0x4) + /* 40Gb (NRZ: 10G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_40GB UINT32_C(0x8) + /* 50Gb (NRZ: 25G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_50GB UINT32_C(0x10) + /* 100Gb (NRZ: 25G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_100GB UINT32_C(0x20) + /* 50Gb (PAM4-56: 50G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_50GB_PAM4_56 UINT32_C(0x40) + /* 100Gb (PAM4-56: 50G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_100GB_PAM4_56 UINT32_C(0x80) + /* 200Gb (PAM4-56: 50G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_200GB_PAM4_56 UINT32_C(0x100) + /* 400Gb (PAM4-56: 50G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_400GB_PAM4_56 UINT32_C(0x200) + /* 100Gb (PAM4-112: 100G per lane, 1 lane) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_100GB_PAM4_112 UINT32_C(0x400) + /* 200Gb (PAM4-112: 100G per lane, 2 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_200GB_PAM4_112 UINT32_C(0x800) + /* 400Gb (PAM4-112: 100G per lane, 4 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_400GB_PAM4_112 UINT32_C(0x1000) + /* 800Gb (PAM4-112: 100G per lane, 8 lanes) link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS2_AUTO_MODE_800GB_PAM4_112 UINT32_C(0x2000) + uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -28203,9 +31642,9 @@ typedef struct hwrm_port_phy_i2c_write_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -28294,9 +31733,9 @@ typedef struct hwrm_port_phy_i2c_read_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -28373,9 +31812,9 @@ typedef struct hwrm_port_phy_mdio_write_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -28452,9 +31891,9 @@ typedef struct hwrm_port_phy_mdio_read_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -28846,9 +32285,9 @@ typedef struct hwrm_port_led_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -29142,9 +32581,9 @@ typedef struct hwrm_port_led_qcfg_output { uint8_t unused_4[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -29460,9 +32899,9 @@ typedef struct hwrm_port_led_qcaps_output { uint8_t unused_4[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -29508,7 +32947,8 @@ typedef struct hwrm_port_prbs_test_input { uint64_t resp_data_addr; /* * Size of the buffer pointed to by resp_data_addr. The firmware may - * use this entire buffer or less than the entire buffer, but never more. + * use this entire buffer or less than the entire buffer, but never + * more. */ uint16_t data_len; uint16_t flags; @@ -29577,6 +33017,8 @@ typedef struct hwrm_port_prbs_test_input { * If fec_stat_t0_t7 is set, fec_stat_t8_t15 field will be ignored. */ #define HWRM_PORT_PRBS_TEST_INPUT_PRBS_CONFIG_FEC_STAT_T8_T15 UINT32_C(0x10) + /* If set, prbs test will run t-code project as well. */ + #define HWRM_PORT_PRBS_TEST_INPUT_PRBS_CONFIG_T_CODE UINT32_C(0x20) /* Duration in seconds to run the PRBS test. */ uint16_t timeout; /* @@ -29617,9 +33059,9 @@ typedef struct hwrm_port_prbs_test_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -29664,13 +33106,20 @@ typedef struct hwrm_port_dsc_dump_input { /* Host address where response diagnostic data is returned. */ uint64_t resp_data_addr; /* - * Size of the buffer pointed to by resp_data_addr. The firmware + * Size of the host buffer pointed to by resp_data_addr. The firmware * may use this entire buffer or less than the entire buffer, but * never more. */ uint16_t data_len; uint16_t unused_0; - uint32_t unused_1; + /* + * Ignored by the start command. + * In legacy buffer mode, this is ignored. The transfer starts + * at buffer offset zero and must be transferred in one command. + * In big buffer mode, this is the offset into the NIC buffer for + * the current retrieve command to start. + */ + uint32_t data_offset; /* Port ID of port where dsc dump to be collected. */ uint16_t port_id; /* Diag level specified by the user */ @@ -29703,20 +33152,48 @@ typedef struct hwrm_port_dsc_dump_input { #define HWRM_PORT_DSC_DUMP_INPUT_DIAG_LEVEL_SRDS_DIAG_TIMESTAMP UINT32_C(0xc) #define HWRM_PORT_DSC_DUMP_INPUT_DIAG_LEVEL_LAST HWRM_PORT_DSC_DUMP_INPUT_DIAG_LEVEL_SRDS_DIAG_TIMESTAMP /* - * This field is a lane number - * on which to collect the dsc dump + * This field is the lane number on which to collect the dsc dump. + * If this is 0xFFFF, the dsc dump will be collected for all lanes, + * if the hardware and firmware support this feature. */ uint16_t lane_number; - /* - * Configuration bits. - * Use enable bit to start dsc dump or retrieve dump - */ + /* Configuration bits. */ uint16_t dsc_dump_config; /* * Set 0 to retrieve the dsc dump * Set 1 to start the dsc dump + * Some configuration parameter for the dscdump report are + * set by the start request, and can not be modified until the + * retrieve operation is complete, on the next start. */ #define HWRM_PORT_DSC_DUMP_INPUT_DSC_DUMP_CONFIG_START_RETRIEVE UINT32_C(0x1) + /* + * Set 0 to limit the report size to 65535 bytes. + * Set 1 to allow a larger buffer size. + * This can only be set 1 in the start operation. + * If this is set 0 in the start operation, the firmware will + * assume it needs to only expose up to 65535 bytes of the report, + * and only allow a single retrieve operation to retrieve the + * entire report. This mode will truncate longer reports. + * If this is set 1 in the start operation, the firmware will + * report the full size of the report (up to the firmware's limit), + * permit retrieve operations to hold the buffer using the config + * defer_close, and honour the data_offset value so later data + * in the report can be retrieved. + */ + #define HWRM_PORT_DSC_DUMP_INPUT_DSC_DUMP_CONFIG_BIG_BUFFER UINT32_C(0x2) + /* + * Set 0 on the last 'retrieve' to release the firmware buffer + * Set 1 on the other 'retrieve' to hold the firmware buffer + * This only affects retrieve operations. + * In big_buffer mode, this allows the driver or tool to tell + * the firmware to keep the report around, as it intends to read + * more of it in. The final read must set this to zero, to tell + * the firmware the report buffer can be released. + * This only works if the start request specified big_buffer as + * one; it is ignored otherwise. + */ + #define HWRM_PORT_DSC_DUMP_INPUT_DSC_DUMP_CONFIG_DEFER_CLOSE UINT32_C(0x4) } hwrm_port_dsc_dump_input_t, *phwrm_port_dsc_dump_input_t; /* hwrm_port_dsc_dump_output (size:128b/16B) */ @@ -29730,15 +33207,49 @@ typedef struct hwrm_port_dsc_dump_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Total length of stored data. */ + /* + * Total length of stored data; if big_buffer is one, this + * only contains the lower 16 bits of the total length. + * In legacy buffer mode, this is zero in the 'start' response. + * In big buffer mode, this has the size of the report even + * in the 'start' response. + * In both modes, this contains the number of bytes written + * to the host in 'retrieve' responses. + */ uint16_t total_data_len; - uint16_t unused_0; - uint8_t unused_1[3]; + /* + * The upper 16 bits of the total length of stored data. + * In legacy buffer mode, this will always be zero. + * In big buffer mode, this will be populated even in the + * 'start' response. + * This is always zero for 'retrieve' responses. + */ + uint16_t total_data_len_high; + uint8_t unused_1[2]; + /* Result information bits. */ + uint8_t flags; + /* + * Set according to the start request's input big_buffer. + * If this is zero, it indicates the function is acting per + * legacy behaviour -- it will report a buffer size up to almost + * 64KiB, and allow only one retrieval request before releasing + * the firmware buffer containing the report (total_data_len_high + * will be zero). The request's data_offset field and defer_close + * and use_offset config flags are ignored. + * If this is one, it indicates support for (and request of) + * support for larger reports. The full 32b report size (up to the + * firmware buffer limit) is provided by the start response in + * total_data_len (low 16b) and total_data_len_high (high 16b), + * and retrieve requests may keep the buffer using the defer_close + * flag, and retrieve the later parts of the report using the + * data_offset field. + */ + #define HWRM_PORT_DSC_DUMP_OUTPUT_FLAGS_BIG_BUFFER UINT32_C(0x1) /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -29865,7 +33376,7 @@ typedef struct hwrm_port_sfp_sideband_cfg_output { uint8_t unused[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. When * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. @@ -29980,7 +33491,7 @@ typedef struct hwrm_port_sfp_sideband_qcfg_output { uint8_t unused[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. When * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. @@ -30035,7 +33546,7 @@ typedef struct hwrm_port_phy_mdio_bus_acquire_input { */ uint16_t client_id; /* - * Timeout in milli seconds, MDIO BUS will be released automatically + * Timeout in milliseconds, MDIO BUS will be released automatically * after this time, if another mdio acquire command is not received * within the timeout window from the same client. * A 0xFFFF will hold the bus until this bus is released. @@ -30064,9 +33575,9 @@ typedef struct hwrm_port_phy_mdio_bus_acquire_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -30135,9 +33646,9 @@ typedef struct hwrm_port_phy_mdio_bus_release_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -30182,10 +33693,20 @@ typedef struct hwrm_port_tx_fir_cfg_input { /* Modulation types of TX FIR: NRZ, PAM4. */ uint8_t mod_type; /* For NRZ */ - #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_NRZ UINT32_C(0x0) + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_NRZ UINT32_C(0x0) /* For PAM4 */ - #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_PAM4 UINT32_C(0x1) - #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_LAST HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_PAM4 + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_PAM4 UINT32_C(0x1) + /* For Optical NRZ */ + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_C2M_NRZ UINT32_C(0x2) + /* For Optical PAM4 */ + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_C2M_PAM4 UINT32_C(0x3) + /* For DAC PAM4 112G */ + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_PAM4_112 UINT32_C(0x4) + /* For Optical PAM4 112G */ + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_C2M_PAM4_112G UINT32_C(0x5) + /* For LPO PAM4 112G */ + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_LPO_PAM4_112G UINT32_C(0x6) + #define HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_LAST HWRM_PORT_TX_FIR_CFG_INPUT_MOD_TYPE_LPO_PAM4_112G /* The lane mask of the lane TX FIR will be configured. */ uint8_t lane_mask; uint8_t unused_0[2]; @@ -30214,9 +33735,9 @@ typedef struct hwrm_port_tx_fir_cfg_output { uint8_t unused[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -30261,10 +33782,20 @@ typedef struct hwrm_port_tx_fir_qcfg_input { /* Modulation types of TX FIR: NRZ, PAM4. */ uint8_t mod_type; /* For NRZ */ - #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_NRZ UINT32_C(0x0) - /* For PAM4 */ - #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_PAM4 UINT32_C(0x1) - #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_LAST HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_PAM4 + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_NRZ UINT32_C(0x0) + /* For PAM4 56G */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_PAM4 UINT32_C(0x1) + /* For Optical NRZ */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_C2M_NRZ UINT32_C(0x2) + /* For Optical PAM4 56G */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_C2M_PAM4 UINT32_C(0x3) + /* For DAC PAM4 112G */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_PAM4_112 UINT32_C(0x4) + /* For Optical PAM4 112G */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_C2M_PAM4_112 UINT32_C(0x5) + /* For LPO PAM4 112G */ + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_LPO_PAM4_112 UINT32_C(0x6) + #define HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_LAST HWRM_PORT_TX_FIR_QCFG_INPUT_MOD_TYPE_LPO_PAM4_112 /* The ID of the lane TX FIR will be queried. */ uint8_t lane_id; uint8_t unused[6]; @@ -30292,9 +33823,9 @@ typedef struct hwrm_port_tx_fir_qcfg_output { uint8_t unused[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -30398,9 +33929,9 @@ typedef struct hwrm_port_ep_tx_cfg_input { */ uint8_t ep2_min_bw; /* - * Specifies the maximum portion of the port's bandwidth that the set of - * PFs and VFs on PCIe endpoint 2 may use. The value is a percentage of - * the link bandwidth, from 0 to 100. A value of 0 indicates no + * Specifies the maximum portion of the port's bandwidth that the set + * of PFs and VFs on PCIe endpoint 2 may use. The value is a percentage + * of the link bandwidth, from 0 to 100. A value of 0 indicates no * maximum rate. */ uint8_t ep2_max_bw; @@ -30675,9 +34206,9 @@ typedef struct hwrm_port_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -30756,15 +34287,224 @@ typedef struct hwrm_port_qcfg_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; } hwrm_port_qcfg_output_t, *phwrm_port_qcfg_output_t; /*********************** + * hwrm_port_mac_qcaps * + ***********************/ + + +/* hwrm_port_mac_qcaps_input (size:192b/24B) */ + +typedef struct hwrm_port_mac_qcaps_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Port ID of port that is being queried. */ + uint16_t port_id; + uint8_t unused_0[6]; +} hwrm_port_mac_qcaps_input_t, *phwrm_port_mac_qcaps_input_t; + +/* hwrm_port_mac_qcaps_output (size:128b/16B) */ + +typedef struct hwrm_port_mac_qcaps_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* MAC capability flags */ + uint8_t flags; + /* + * If set to 1, then this field indicates that the + * MAC does not support local loopback. + */ + #define HWRM_PORT_MAC_QCAPS_OUTPUT_FLAGS_LOCAL_LPBK_NOT_SUPPORTED UINT32_C(0x1) + /* + * If set to 1, then this field indicates that the + * MAC is capable of supporting remote loopback. + */ + #define HWRM_PORT_MAC_QCAPS_OUTPUT_FLAGS_REMOTE_LPBK_SUPPORTED UINT32_C(0x2) + uint8_t unused_0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_port_mac_qcaps_output_t, *phwrm_port_mac_qcaps_output_t; + +/********************* + * hwrm_port_poe_cfg * + *********************/ + + +/* hwrm_port_poe_cfg_input (size:192b/24B) */ + +typedef struct hwrm_port_poe_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Expander port index for which PoE has to be enabled/disabled */ + uint8_t exp_port_idx; + /* PoE enable/disable flag */ + uint8_t flags; + /* This field indicates that the PoE has to be enabled. */ + #define HWRM_PORT_POE_CFG_INPUT_FLAGS_ENABLE_POE UINT32_C(0x1) + uint8_t unused_0[6]; +} hwrm_port_poe_cfg_input_t, *phwrm_port_poe_cfg_input_t; + +/* hwrm_port_poe_cfg_output (size:128b/16B) */ + +typedef struct hwrm_port_poe_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_port_poe_cfg_output_t, *phwrm_port_poe_cfg_output_t; + +/********************** + * hwrm_port_poe_qcfg * + **********************/ + + +/* hwrm_port_poe_qcfg_input (size:192b/24B) */ + +typedef struct hwrm_port_poe_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Expander port which is queried */ + uint8_t exp_port_idx; + uint8_t unused_0[7]; +} hwrm_port_poe_qcfg_input_t, *phwrm_port_poe_qcfg_input_t; + +/* hwrm_port_poe_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_port_poe_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* This field indicates if the PoE is enabled/disabled */ + uint8_t status; + /* This field indicates that the PoE is enabled. */ + #define HWRM_PORT_POE_QCFG_OUTPUT_STATUS_POE_ENABLED UINT32_C(0x1) + uint8_t unused_0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_port_poe_qcfg_output_t, *phwrm_port_poe_qcfg_output_t; + +/*********************** * hwrm_queue_qportcfg * ***********************/ @@ -31299,8 +35039,8 @@ typedef struct hwrm_queue_qportcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31396,8 +35136,8 @@ typedef struct hwrm_queue_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31441,9 +35181,9 @@ typedef struct hwrm_queue_cfg_input { uint64_t resp_addr; uint32_t flags; /* - * Enumeration denoting the RX, TX, or both directions applicable to the resource. - * This enumeration is used for resources that are similar for both - * TX and RX paths of the chip. + * Enumeration denoting the RX, TX, or both directions applicable to + * the resource. This enumeration is used for resources that are + * similar for both TX and RX paths of the chip. */ #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_MASK UINT32_C(0x3) #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_SFT 0 @@ -31500,8 +35240,8 @@ typedef struct hwrm_queue_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31600,8 +35340,8 @@ typedef struct hwrm_queue_pfcenable_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31700,8 +35440,8 @@ typedef struct hwrm_queue_pfcenable_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31851,8 +35591,8 @@ typedef struct hwrm_queue_pri2cos_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -31896,9 +35636,9 @@ typedef struct hwrm_queue_pri2cos_cfg_input { uint64_t resp_addr; uint32_t flags; /* - * Enumeration denoting the RX, TX, or both directions applicable to the resource. - * This enumeration is used for resources that are similar for both - * TX and RX paths of the chip. + * Enumeration denoting the RX, TX, or both directions applicable to + * the resource. This enumeration is used for resources that are + * similar for both TX and RX paths of the chip. */ #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_MASK UINT32_C(0x3) #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_SFT 0 @@ -31974,7 +35714,7 @@ typedef struct hwrm_queue_pri2cos_cfg_input { */ uint8_t pri1_cos_queue_id; /* - * CoS Queue assigned to priority 2 This value can only + * CoS Queue assigned to priority 2. This value can only * be changed before traffic has started. */ uint8_t pri2_cos_queue_id; @@ -32021,8 +35761,8 @@ typedef struct hwrm_queue_pri2cos_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -32794,8 +36534,8 @@ typedef struct hwrm_queue_cos2bw_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -33608,8 +37348,8 @@ typedef struct hwrm_queue_cos2bw_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -33680,8 +37420,8 @@ typedef struct hwrm_queue_dscp_qcaps_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -33765,8 +37505,8 @@ typedef struct hwrm_queue_dscp2pri_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -33860,8 +37600,8 @@ typedef struct hwrm_queue_dscp2pri_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -33945,8 +37685,8 @@ typedef struct hwrm_queue_mpls_qcaps_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34068,8 +37808,8 @@ typedef struct hwrm_queue_mplstc2pri_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34170,7 +37910,7 @@ typedef struct hwrm_queue_mplstc2pri_cfg_input { */ uint8_t tc1_pri_queue_id; /* - * pri assigned to MPLS TC(EXP) 2 This value can only + * pri assigned to MPLS TC(EXP) 2. This value can only * be changed before traffic has started. */ uint8_t tc2_pri_queue_id; @@ -34216,8 +37956,8 @@ typedef struct hwrm_queue_mplstc2pri_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34288,8 +38028,8 @@ typedef struct hwrm_queue_vlanpri_qcaps_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34403,8 +38143,8 @@ typedef struct hwrm_queue_vlanpri2pri_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34551,8 +38291,8 @@ typedef struct hwrm_queue_vlanpri2pri_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34683,8 +38423,8 @@ typedef struct hwrm_queue_global_cfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34826,13 +38566,1657 @@ typedef struct hwrm_queue_global_qcfg_output { /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; } hwrm_queue_global_qcfg_output_t, *phwrm_queue_global_qcfg_output_t; +/**************************************** + * hwrm_queue_adptv_qos_rx_feature_qcfg * + ****************************************/ + + +/* hwrm_queue_adptv_qos_rx_feature_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_rx_feature_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_adptv_qos_rx_feature_qcfg_input_t, *phwrm_queue_adptv_qos_rx_feature_qcfg_input_t; + +/* hwrm_queue_adptv_qos_rx_feature_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_rx_feature_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * Bitmask indicating which RX CoS queues are enabled or disabled. + * + * Each bit represents a specific queue where bit 0 represents + * queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is not enabled. + * A value of 1 indicates that the queue is enabled. + */ + uint8_t queue_enable; + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE UINT32_C(0x1) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_DISABLED UINT32_C(0x0) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE UINT32_C(0x2) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_DISABLED (UINT32_C(0x0) << 1) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE UINT32_C(0x4) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_DISABLED (UINT32_C(0x0) << 2) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE UINT32_C(0x8) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_DISABLED (UINT32_C(0x0) << 3) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE UINT32_C(0x10) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_DISABLED (UINT32_C(0x0) << 4) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE UINT32_C(0x20) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_DISABLED (UINT32_C(0x0) << 5) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE UINT32_C(0x40) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_DISABLED (UINT32_C(0x0) << 6) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE UINT32_C(0x80) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_DISABLED (UINT32_C(0x0) << 7) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED + /* + * Bitmask indicating which CoS queues are lossy or lossless. + * This setting is kept same across Rx and Tx directions, despite + * the name mentioning only Rx. Each bit represents a specific queue + * where bit 0 represents queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is lossy. + * A value of 1 indicates that the queue is lossless. + */ + uint8_t queue_mode; + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID0_MODE UINT32_C(0x1) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID0_MODE_LOSSY UINT32_C(0x0) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID0_MODE_LOSSLESS UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID0_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID0_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID1_MODE UINT32_C(0x2) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID1_MODE_LOSSY (UINT32_C(0x0) << 1) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID1_MODE_LOSSLESS (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID1_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID1_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID2_MODE UINT32_C(0x4) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID2_MODE_LOSSY (UINT32_C(0x0) << 2) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID2_MODE_LOSSLESS (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID2_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID2_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID3_MODE UINT32_C(0x8) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID3_MODE_LOSSY (UINT32_C(0x0) << 3) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID3_MODE_LOSSLESS (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID3_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID3_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID4_MODE UINT32_C(0x10) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID4_MODE_LOSSY (UINT32_C(0x0) << 4) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID4_MODE_LOSSLESS (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID4_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID4_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID5_MODE UINT32_C(0x20) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID5_MODE_LOSSY (UINT32_C(0x0) << 5) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID5_MODE_LOSSLESS (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID5_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID5_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID6_MODE UINT32_C(0x40) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID6_MODE_LOSSY (UINT32_C(0x0) << 6) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID6_MODE_LOSSLESS (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID6_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID6_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID7_MODE UINT32_C(0x80) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID7_MODE_LOSSY (UINT32_C(0x0) << 7) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID7_MODE_LOSSLESS (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID7_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG_OUTPUT_QUEUE_MODE_QID7_MODE_LOSSLESS + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_rx_feature_qcfg_output_t, *phwrm_queue_adptv_qos_rx_feature_qcfg_output_t; + +/*************************************** + * hwrm_queue_adptv_qos_rx_feature_cfg * + ***************************************/ + + +/* hwrm_queue_adptv_qos_rx_feature_cfg_input (size:192b/24B) */ + +typedef struct hwrm_queue_adptv_qos_rx_feature_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* This bit must be '1' for the queue_enable field to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_ENABLES_QUEUE_ENABLE UINT32_C(0x1) + /* This bit must be '1' for the queue_mode field to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_ENABLES_QUEUE_MODE UINT32_C(0x2) + /* + * Bitmask indicating which RX CoS queues are enabled or disabled. + * + * Each bit represents a specific queue where bit 0 represents + * queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is not enabled. + * A value of 1 indicates that the queue is enabled. + */ + uint8_t queue_enable; + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE UINT32_C(0x1) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_DISABLED UINT32_C(0x0) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE UINT32_C(0x2) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_DISABLED (UINT32_C(0x0) << 1) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE UINT32_C(0x4) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_DISABLED (UINT32_C(0x0) << 2) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE UINT32_C(0x8) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_DISABLED (UINT32_C(0x0) << 3) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE UINT32_C(0x10) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_DISABLED (UINT32_C(0x0) << 4) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE UINT32_C(0x20) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_DISABLED (UINT32_C(0x0) << 5) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE UINT32_C(0x40) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_DISABLED (UINT32_C(0x0) << 6) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE UINT32_C(0x80) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_DISABLED (UINT32_C(0x0) << 7) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED + /* + * Bitmask indicating which CoS queues are lossy or lossless. + * This setting is kept symmetric (or same) across Tx and Rx. + * Each bit represents a specific queue where bit 0 represents + * queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is lossy. + * A value of 1 indicates that the queue is lossless. + */ + uint8_t queue_mode; + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID0_MODE UINT32_C(0x1) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID0_MODE_LOSSY UINT32_C(0x0) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID0_MODE_LOSSLESS UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID0_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID0_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID1_MODE UINT32_C(0x2) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID1_MODE_LOSSY (UINT32_C(0x0) << 1) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID1_MODE_LOSSLESS (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID1_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID1_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID2_MODE UINT32_C(0x4) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID2_MODE_LOSSY (UINT32_C(0x0) << 2) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID2_MODE_LOSSLESS (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID2_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID2_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID3_MODE UINT32_C(0x8) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID3_MODE_LOSSY (UINT32_C(0x0) << 3) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID3_MODE_LOSSLESS (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID3_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID3_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID4_MODE UINT32_C(0x10) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID4_MODE_LOSSY (UINT32_C(0x0) << 4) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID4_MODE_LOSSLESS (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID4_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID4_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID5_MODE UINT32_C(0x20) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID5_MODE_LOSSY (UINT32_C(0x0) << 5) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID5_MODE_LOSSLESS (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID5_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID5_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID6_MODE UINT32_C(0x40) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID6_MODE_LOSSY (UINT32_C(0x0) << 6) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID6_MODE_LOSSLESS (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID6_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID6_MODE_LOSSLESS + /* If set to 0, then the queue is lossy, else lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID7_MODE UINT32_C(0x80) + /* Lossy (best-effort). */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID7_MODE_LOSSY (UINT32_C(0x0) << 7) + /* Lossless. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID7_MODE_LOSSLESS (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID7_MODE_LAST HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_CFG_INPUT_QUEUE_MODE_QID7_MODE_LOSSLESS + uint8_t unused_0[2]; +} hwrm_queue_adptv_qos_rx_feature_cfg_input_t, *phwrm_queue_adptv_qos_rx_feature_cfg_input_t; + +/* hwrm_queue_adptv_qos_rx_feature_cfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_rx_feature_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_rx_feature_cfg_output_t, *phwrm_queue_adptv_qos_rx_feature_cfg_output_t; + +/**************************************** + * hwrm_queue_adptv_qos_tx_feature_qcfg * + ****************************************/ + + +/* hwrm_queue_adptv_qos_tx_feature_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_tx_feature_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_adptv_qos_tx_feature_qcfg_input_t, *phwrm_queue_adptv_qos_tx_feature_qcfg_input_t; + +/* hwrm_queue_adptv_qos_tx_feature_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_tx_feature_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * Bitmask indicating which TX CoS queues are enabled or disabled. + * + * Each bit represents a specific queue where bit 0 represents + * queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is not enabled. + * A value of 1 indicates that the queue is enabled. + */ + uint8_t queue_enable; + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE UINT32_C(0x1) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_DISABLED UINT32_C(0x0) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE UINT32_C(0x2) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_DISABLED (UINT32_C(0x0) << 1) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE UINT32_C(0x4) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_DISABLED (UINT32_C(0x0) << 2) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE UINT32_C(0x8) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_DISABLED (UINT32_C(0x0) << 3) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE UINT32_C(0x10) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_DISABLED (UINT32_C(0x0) << 4) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE UINT32_C(0x20) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_DISABLED (UINT32_C(0x0) << 5) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE UINT32_C(0x40) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_DISABLED (UINT32_C(0x0) << 6) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE UINT32_C(0x80) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_DISABLED (UINT32_C(0x0) << 7) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG_OUTPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED + uint8_t unused_0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_tx_feature_qcfg_output_t, *phwrm_queue_adptv_qos_tx_feature_qcfg_output_t; + +/*************************************** + * hwrm_queue_adptv_qos_tx_feature_cfg * + ***************************************/ + + +/* hwrm_queue_adptv_qos_tx_feature_cfg_input (size:192b/24B) */ + +typedef struct hwrm_queue_adptv_qos_tx_feature_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* This bit must be '1' for the queue_enable field to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_ENABLES_QUEUE_ENABLE UINT32_C(0x1) + /* + * Bitmask indicating which TX CoS queues are enabled or disabled. + * + * Each bit represents a specific queue where bit 0 represents + * queue 0 and bit 7 represents queue 7. + * A value of 0 indicates that the queue is not enabled. + * A value of 1 indicates that the queue is enabled. + */ + uint8_t queue_enable; + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE UINT32_C(0x1) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_DISABLED UINT32_C(0x0) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED UINT32_C(0x1) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID0_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE UINT32_C(0x2) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_DISABLED (UINT32_C(0x0) << 1) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED (UINT32_C(0x1) << 1) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID1_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE UINT32_C(0x4) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_DISABLED (UINT32_C(0x0) << 2) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED (UINT32_C(0x1) << 2) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID2_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE UINT32_C(0x8) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_DISABLED (UINT32_C(0x0) << 3) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED (UINT32_C(0x1) << 3) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID3_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE UINT32_C(0x10) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_DISABLED (UINT32_C(0x0) << 4) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED (UINT32_C(0x1) << 4) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID4_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE UINT32_C(0x20) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_DISABLED (UINT32_C(0x0) << 5) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED (UINT32_C(0x1) << 5) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID5_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE UINT32_C(0x40) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_DISABLED (UINT32_C(0x0) << 6) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED (UINT32_C(0x1) << 6) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID6_ENABLE_ENABLED + /* If set to 1, then the queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE UINT32_C(0x80) + /* Queue is disabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_DISABLED (UINT32_C(0x0) << 7) + /* Queue is enabled. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED (UINT32_C(0x1) << 7) + #define HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_LAST HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_CFG_INPUT_QUEUE_ENABLE_QID7_ENABLE_ENABLED + uint8_t unused_0[3]; +} hwrm_queue_adptv_qos_tx_feature_cfg_input_t, *phwrm_queue_adptv_qos_tx_feature_cfg_input_t; + +/* hwrm_queue_adptv_qos_tx_feature_cfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_tx_feature_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_tx_feature_cfg_output_t, *phwrm_queue_adptv_qos_tx_feature_cfg_output_t; + +/******************** + * hwrm_queue_qcaps * + ********************/ + + +/* hwrm_queue_qcaps_input (size:128b/16B) */ + +typedef struct hwrm_queue_qcaps_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_qcaps_input_t, *phwrm_queue_qcaps_input_t; + +/* hwrm_queue_qcaps_output (size:256b/32B) */ + +typedef struct hwrm_queue_qcaps_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Adaptive QoS RX feature parameter capability flags. */ + uint32_t rx_feature_params; + /* + * When this bit is '1' the capability to configure queue_enable + * is supported. + * If set to '0', then the capability to configure queue_enable + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_FEATURE_PARAMS_QUEUE_ENABLE_CAP UINT32_C(0x1) + /* + * When this bit is '1' the capability to configure queue_mode + * is supported. + * If set to '0', then the capability to configure queue_mode + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_FEATURE_PARAMS_QUEUE_MODE_CAP UINT32_C(0x2) + /* Adaptive QoS TX feature parameter capability flags. */ + uint32_t tx_feature_params; + /* + * When this bit is '1' the capability to configure queue_enable + * is supported. + * If set to '0', then the capability to configure queue_enable + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_FEATURE_PARAMS_QUEUE_ENABLE_CAP UINT32_C(0x1) + /* + * The maximum number of queues that can be configured on this device. + * Valid values range from 1 through 8. + */ + uint8_t max_configurable_queues; + uint8_t unused_0[3]; + /* Adaptive QoS RX tuning parameter capability flags. */ + uint32_t rx_tuning_params; + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_WFQ_COST_CAP UINT32_C(0x1) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_WFQ_UPPER_FACTOR_CAP UINT32_C(0x2) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_HYST_WINDOW_SIZE_FACTOR_CAP UINT32_C(0x4) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_PCIE_BW_EFF_CAP UINT32_C(0x8) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_XOFF_HEADROOM_FACTOR_CAP UINT32_C(0x10) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_L2_MIN_LATENCY_CAP UINT32_C(0x20) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_L2_MAX_LATENCY_CAP UINT32_C(0x40) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_ROCE_MIN_LATENCY_CAP UINT32_C(0x80) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_ROCE_MAX_LATENCY_CAP UINT32_C(0x100) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_L2_PIPE_COS_LATENCY_CAP UINT32_C(0x200) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_ROCE_PIPE_COS_LATENCY_CAP UINT32_C(0x400) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_COS_SHARED_MIN_RATIO_CAP UINT32_C(0x800) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_RSVD_CELLS_LIMIT_RATIO_CAP UINT32_C(0x1000) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_RX_TUNING_PARAMS_SHAPER_REFILL_TIMER_CAP UINT32_C(0x2000) + /* Adaptive QoS TX tuning parameter capability flags. */ + uint32_t tx_tuning_params; + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_WFQ_COST_CAP UINT32_C(0x1) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_WFQ_UPPER_FACTOR_CAP UINT32_C(0x2) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_HYST_WINDOW_SIZE_FACTOR_CAP UINT32_C(0x4) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_RSVD_CELLS_LIMIT_RATIO_CAP UINT32_C(0x8) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_L2_MIN_LATENCY_CAP UINT32_C(0x10) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_L2_MAX_LATENCY_CAP UINT32_C(0x20) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_ROCE_MIN_LATENCY_CAP UINT32_C(0x40) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_ROCE_MAX_LATENCY_CAP UINT32_C(0x80) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_MAX_TBM_CELLS_PRERESERVED_CAP UINT32_C(0x100) + /* + * When this bit is '1' the capability to configure the option + * is supported. + * If set to '0', then the capability to configure the option + * is not supported. + */ + #define HWRM_QUEUE_QCAPS_OUTPUT_TX_TUNING_PARAMS_SHAPER_REFILL_TIMER_CAP UINT32_C(0x200) + uint8_t unused_1[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_qcaps_output_t, *phwrm_queue_qcaps_output_t; + +/*************************************** + * hwrm_queue_adptv_qos_rx_tuning_qcfg * + ***************************************/ + + +/* hwrm_queue_adptv_qos_rx_tuning_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_rx_tuning_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_adptv_qos_rx_tuning_qcfg_input_t, *phwrm_queue_adptv_qos_rx_tuning_qcfg_input_t; + +/* hwrm_queue_adptv_qos_rx_tuning_qcfg_output (size:576b/72B) */ + +typedef struct hwrm_queue_adptv_qos_rx_tuning_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Indicates max credit as required by hardware. */ + uint32_t wfq_cost; + /* + * Specifies a factor that determines the upper bound for each + * cos_wfq_credit_weight. + */ + uint32_t wfq_upper_factor; + /* + * The algorithm multiplies this factor by the MRU size to compute the + * hysteresis window size which in turn is used in deassert + * threshold calculations. + */ + uint32_t hyst_window_size_factor; + /* + * Specifies PCIe BW efficiency in the range of 0-100%. System + * characterization determines the value of this parameter. A value of + * less than 100% accounts for internal PCIe over-subscription. The + * algorithm uses this parameter to determine the PCIe BW available + * for transferring received packets to the host. + */ + uint32_t pcie_bw_eff; + /* Scales the number of cells for xoff. */ + uint32_t xoff_headroom_factor; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_max_latency; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_max_latency; + /* + * The algorithm uses this parameter to calculate the number of cells + * to be excluded from the total buffer pool to account for the + * latency of pipeline post RE_DEC to PCIe block. Its value is derived + * from system characterization. + */ + uint32_t l2_pipe_cos_latency; + /* + * The algorithm uses this parameter to calculate the number of cells + * to be excluded from the total buffer pool to account for the + * latency of pipeline post RE_DEC to PCIe block. Its value is derived + * from system characterization. + */ + uint32_t roce_pipe_cos_latency; + /* Sets the minimum number of shared cells each cos queue can have. */ + uint32_t cos_shared_min_ratio; + /* + * The parameter limits the total reserved cells. If the computed + * total reserved cells becomes larger than rsvd_cells_limit_ratio x + * port_cells_avail, then the reserved cells are set to the limit + * value. Its range of values is 0-50%. + */ + uint32_t rsvd_cells_limit_ratio; + /* + * This parameter is used to compute the time interval for + * replenishing the shaper credit buckets for all RX cos queues. + */ + uint32_t shaper_refill_timer; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_rx_tuning_qcfg_output_t, *phwrm_queue_adptv_qos_rx_tuning_qcfg_output_t; + +/************************************** + * hwrm_queue_adptv_qos_rx_tuning_cfg * + **************************************/ + + +/* hwrm_queue_adptv_qos_rx_tuning_cfg_input (size:640b/80B) */ + +typedef struct hwrm_queue_adptv_qos_rx_tuning_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_WFQ_COST UINT32_C(0x1) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_WFQ_UPPER_FACTOR UINT32_C(0x2) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_HYST_WINDOW_SIZE_FACTOR UINT32_C(0x4) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_PCIE_BW_EFF UINT32_C(0x8) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_XOFF_HEADROOM_FACTOR UINT32_C(0x10) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_L2_MIN_LATENCY UINT32_C(0x20) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_L2_MAX_LATENCY UINT32_C(0x40) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_ROCE_MIN_LATENCY UINT32_C(0x80) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_ROCE_MAX_LATENCY UINT32_C(0x100) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_L2_PIPE_COS_LATENCY UINT32_C(0x200) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_ROCE_PIPE_COS_LATENCY UINT32_C(0x400) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_COS_SHARED_MIN_RATIO UINT32_C(0x800) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_RSVD_CELLS_LIMIT_RATIO UINT32_C(0x1000) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_RX_TUNING_CFG_INPUT_ENABLES_SHAPER_REFILL_TIMER UINT32_C(0x2000) + /* Indicates max credit as required by hardware. */ + uint32_t wfq_cost; + /* + * Specifies a factor that determines the upper bound for each + * cos_wfq_credit_weight. + */ + uint32_t wfq_upper_factor; + /* + * The algorithm multiplies this factor by the MRU size to compute the + * hysteresis window size which in turn is used in deassert + * threshold calculations. + */ + uint32_t hyst_window_size_factor; + /* + * Specifies PCIe BW efficiency in the range of 0-100%. System + * characterization determines the value of this parameter. A value of + * less than 100% accounts for internal PCIe over-subscription. The + * algorithm uses this parameter to determine the PCIe BW available + * for transferring received packets to the host. + */ + uint32_t pcie_bw_eff; + /* Scales the number of cells for xoff. */ + uint32_t xoff_headroom_factor; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_max_latency; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_max_latency; + /* + * The algorithm uses this parameter to calculate the number of cells + * to be excluded from the total buffer pool to account for the + * latency of pipeline post RE_DEC to PCIe block. Its value is derived + * from system characterization. + */ + uint32_t l2_pipe_cos_latency; + /* + * The algorithm uses this parameter to calculate the number of cells + * to be excluded from the total buffer pool to account for the + * latency of pipeline post RE_DEC to PCIe block. Its value is derived + * from system characterization. + */ + uint32_t roce_pipe_cos_latency; + /* Sets the minimum number of shared cells each cos queue can have. */ + uint32_t cos_shared_min_ratio; + /* + * The parameter limits the total reserved cells. If the computed + * total reserved cells becomes larger than rsvd_cells_limit_ratio x + * port_cells_avail, then the reserved cells are set to the limit + * value. Its range of values is 0-50%. + */ + uint32_t rsvd_cells_limit_ratio; + /* + * This parameter is used to compute the time interval for + * replenishing the shaper credit buckets for all RX cos queues. + */ + uint32_t shaper_refill_timer; + uint8_t unused_0[4]; +} hwrm_queue_adptv_qos_rx_tuning_cfg_input_t, *phwrm_queue_adptv_qos_rx_tuning_cfg_input_t; + +/* hwrm_queue_adptv_qos_rx_tuning_cfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_rx_tuning_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_rx_tuning_cfg_output_t, *phwrm_queue_adptv_qos_rx_tuning_cfg_output_t; + +/*************************************** + * hwrm_queue_adptv_qos_tx_tuning_qcfg * + ***************************************/ + + +/* hwrm_queue_adptv_qos_tx_tuning_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_tx_tuning_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_adptv_qos_tx_tuning_qcfg_input_t, *phwrm_queue_adptv_qos_tx_tuning_qcfg_input_t; + +/* hwrm_queue_adptv_qos_tx_tuning_qcfg_output (size:448b/56B) */ + +typedef struct hwrm_queue_adptv_qos_tx_tuning_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Indicates max credit as required by hardware. */ + uint32_t wfq_cost; + /* + * Specifies a factor that determines the upper bound for each + * cos_wfq_credit_weight. + */ + uint32_t wfq_upper_factor; + /* + * The algorithm multiplies this factor by the MRU size to compute the + * hysteresis window size which in turn is used in deassert + * threshold calculations. + */ + uint32_t hyst_window_size_factor; + /* + * The parameter limits the total reserved cells. If the computed + * total reserved cells becomes larger than rsvd_cells_limit_ratio x + * port_cells_avail, then the reserved cells are set to the limit + * value. Its range of values is 0-50%. + */ + uint32_t rsvd_cells_limit_ratio; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_max_latency; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_max_latency; + /* Specifies the number of reserved cells TRP requires per cos queue. */ + uint32_t max_tbm_cells_prereserved; + /* + * This parameter is used to compute the time interval for + * replenishing the shaper credit buckets for all TX cos queues. + */ + uint32_t shaper_refill_timer; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_tx_tuning_qcfg_output_t, *phwrm_queue_adptv_qos_tx_tuning_qcfg_output_t; + +/************************************** + * hwrm_queue_adptv_qos_tx_tuning_cfg * + **************************************/ + + +/* hwrm_queue_adptv_qos_tx_tuning_cfg_input (size:512b/64B) */ + +typedef struct hwrm_queue_adptv_qos_tx_tuning_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_WFQ_COST UINT32_C(0x1) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_WFQ_UPPER_FACTOR UINT32_C(0x2) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_HYST_WINDOW_SIZE_FACTOR UINT32_C(0x4) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_RSVD_CELLS_LIMIT_RATIO UINT32_C(0x8) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_L2_MIN_LATENCY UINT32_C(0x10) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_L2_MAX_LATENCY UINT32_C(0x20) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_ROCE_MIN_LATENCY UINT32_C(0x40) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_ROCE_MAX_LATENCY UINT32_C(0x80) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_MAX_TBM_CELLS_PRERESERVED UINT32_C(0x100) + /* This bit must be '1' for the option to be configured. */ + #define HWRM_QUEUE_ADPTV_QOS_TX_TUNING_CFG_INPUT_ENABLES_SHAPER_REFILL_TIMER UINT32_C(0x200) + /* Indicates max credit as required by hardware. */ + uint32_t wfq_cost; + /* + * Specifies a factor that determines the upper bound for each + * cos_wfq_credit_weight. + */ + uint32_t wfq_upper_factor; + /* + * The algorithm multiplies this factor by the MRU size to compute the + * hysteresis window size which in turn is used in deassert + * threshold calculations. + */ + uint32_t hyst_window_size_factor; + /* + * The parameter limits the total reserved cells. If the computed + * total reserved cells becomes larger than rsvd_cells_limit_ratio x + * port_cells_avail, then the reserved cells are set to the limit + * value. Its range of values is 0-50%. + */ + uint32_t rsvd_cells_limit_ratio; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for L2. Its value is derived from system + * characterization. + */ + uint32_t l2_max_latency; + /* + * It is used to calculate the number of reserved cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_min_latency; + /* + * It is used to calculate the number of shared cells for cos queues + * configured for RoCE. Its value is derived from system + * characterization. + */ + uint32_t roce_max_latency; + /* Specifies the number of reserved cells TRP requires per cos queue. */ + uint32_t max_tbm_cells_prereserved; + /* + * This parameter is used to compute the time interval for + * replenishing the shaper credit buckets for all TX cos queues. + */ + uint32_t shaper_refill_timer; + uint8_t unused_0[4]; +} hwrm_queue_adptv_qos_tx_tuning_cfg_input_t, *phwrm_queue_adptv_qos_tx_tuning_cfg_input_t; + +/* hwrm_queue_adptv_qos_tx_tuning_cfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_adptv_qos_tx_tuning_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_adptv_qos_tx_tuning_cfg_output_t, *phwrm_queue_adptv_qos_tx_tuning_cfg_output_t; + +/********************************** + * hwrm_queue_pfcwd_timeout_qcaps * + **********************************/ + + +/* hwrm_queue_pfcwd_timeout_qcaps_input (size:128b/16B) */ + +typedef struct hwrm_queue_pfcwd_timeout_qcaps_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_pfcwd_timeout_qcaps_input_t, *phwrm_queue_pfcwd_timeout_qcaps_input_t; + +/* hwrm_queue_pfcwd_timeout_qcaps_output (size:128b/16B) */ + +typedef struct hwrm_queue_pfcwd_timeout_qcaps_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Max configurable pfc watchdog timeout value in msec. */ + uint16_t max_pfcwd_timeout; + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_pfcwd_timeout_qcaps_output_t, *phwrm_queue_pfcwd_timeout_qcaps_output_t; + +/******************************** + * hwrm_queue_pfcwd_timeout_cfg * + ********************************/ + + +/* hwrm_queue_pfcwd_timeout_cfg_input (size:192b/24B) */ + +typedef struct hwrm_queue_pfcwd_timeout_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * pfc watchdog timeout value in msec. + * A value of 0 means firmware will disable the PFC watchdog. + * A value of 0xffff means firmware will reset the timeout + * value to Hardware defaults. Anywhere between 0 to 0xffff is + * valid range for timeout value depending on the Hardware + * capability. + */ + uint16_t pfcwd_timeout_value; + uint8_t unused_0[6]; +} hwrm_queue_pfcwd_timeout_cfg_input_t, *phwrm_queue_pfcwd_timeout_cfg_input_t; + +/* hwrm_queue_pfcwd_timeout_cfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_pfcwd_timeout_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_pfcwd_timeout_cfg_output_t, *phwrm_queue_pfcwd_timeout_cfg_output_t; + +/********************************* + * hwrm_queue_pfcwd_timeout_qcfg * + *********************************/ + + +/* hwrm_queue_pfcwd_timeout_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_queue_pfcwd_timeout_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_queue_pfcwd_timeout_qcfg_input_t, *phwrm_queue_pfcwd_timeout_qcfg_input_t; + +/* hwrm_queue_pfcwd_timeout_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_queue_pfcwd_timeout_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * Current configured pfc watchdog timeout value in msec. + * A value of 0 means PFC watchdog functionality is disabled. + */ + uint16_t pfcwd_timeout_value; + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_queue_pfcwd_timeout_qcfg_output_t, *phwrm_queue_pfcwd_timeout_qcfg_output_t; + /******************* * hwrm_vnic_alloc * *******************/ @@ -34906,9 +40290,9 @@ typedef struct hwrm_vnic_alloc_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -34980,23 +40364,18 @@ typedef struct hwrm_vnic_update_input { #define HWRM_VNIC_UPDATE_INPUT_VNIC_STATE_LAST HWRM_VNIC_UPDATE_INPUT_VNIC_STATE_DROP /* * The metadata format type used in all the RX packet completions - * going through this VNIC. + * going through this VNIC. This value is product specific. Refer to + * the L2 HSI completion ring structures for the detailed + * descriptions. For Thor and Thor2, it corresponds to 'meta_format' + * in 'rx_pkt_cmpl_hi' and 'rx_pkt_v3_cmpl_hi', respectively. */ uint8_t metadata_format_type; - /* No metadata information. */ - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_NONE UINT32_C(0x0) - /* - * Action record pointer (table_scope[4:0], act_rec_ptr[25:0], - * vtag[19:0]). - */ - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_ACT_RECORD_PTR UINT32_C(0x1) - /* Tunnel ID (tunnel_id[31:0], vtag[19:0]) */ - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_TUNNEL_ID UINT32_C(0x2) - /* Custom header data (updated_chdr_data[31:0], vtag[19:0]) */ - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_CUSTOM_HDR_DATA UINT32_C(0x3) - /* Header offsets (hdr_offsets[31:0], vtag[19:0]) */ - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_HDR_OFFSETS UINT32_C(0x4) - #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_LAST HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_HDR_OFFSETS + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_0 UINT32_C(0x0) + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_1 UINT32_C(0x1) + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_2 UINT32_C(0x2) + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_3 UINT32_C(0x3) + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_4 UINT32_C(0x4) + #define HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_LAST HWRM_VNIC_UPDATE_INPUT_METADATA_FORMAT_TYPE_4 /* * The maximum receive unit of the vnic. * Each vnic is associated with a function. @@ -35023,7 +40402,7 @@ typedef struct hwrm_vnic_update_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -35087,9 +40466,9 @@ typedef struct hwrm_vnic_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -35237,25 +40616,28 @@ typedef struct hwrm_vnic_cfg_input { #define HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID UINT32_C(0x40) /* This bit must be '1' for the queue_id field to be configured. */ #define HWRM_VNIC_CFG_INPUT_ENABLES_QUEUE_ID UINT32_C(0x80) - /* This bit must be '1' for the rx_csum_v2_mode field to be configured. */ + /* + * This bit must be '1' for the rx_csum_v2_mode field to be + * configured. + */ #define HWRM_VNIC_CFG_INPUT_ENABLES_RX_CSUM_V2_MODE UINT32_C(0x100) /* This bit must be '1' for the l2_cqe_mode field to be configured. */ #define HWRM_VNIC_CFG_INPUT_ENABLES_L2_CQE_MODE UINT32_C(0x200) /* Logical vnic ID */ uint16_t vnic_id; /* - * Default Completion ring for the VNIC. This ring will + * Default Completion ring for the VNIC. This ring will * be chosen if packet does not match any RSS rules and if * there is no COS rule. */ uint16_t dflt_ring_grp; /* - * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if + * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if * there is no RSS rule. */ uint16_t rss_rule; /* - * RSS ID for COS rule/table structure. 0xFF... (All Fs) if + * RSS ID for COS rule/table structure. 0xFF... (All Fs) if * there is no COS rule. */ uint16_t cos_rule; @@ -35274,7 +40656,7 @@ typedef struct hwrm_vnic_cfg_input { */ uint16_t mru; /* - * Default Rx ring for the VNIC. This ring will + * Default Rx ring for the VNIC. This ring will * be chosen if packet does not match any RSS rules. * The aggregation ring associated with the Rx ring is * implied based on the Rx ring specified when the @@ -35282,16 +40664,17 @@ typedef struct hwrm_vnic_cfg_input { */ uint16_t default_rx_ring_id; /* - * Default completion ring for the VNIC. This ring will + * Default completion ring for the VNIC. This ring will * be chosen if packet does not match any RSS rules. */ uint16_t default_cmpl_ring_id; /* - * When specified, only incoming packets classified to the specified CoS - * queue ID will be arriving on this VNIC. Packet priority to CoS mapping - * rules can be specified using HWRM_QUEUE_PRI2COS_CFG. In this mode, - * ntuple filters with VNIC destination specified are invalid since they - * conflict with the CoS to VNIC steering rules in this mode. + * When specified, only incoming packets classified to the specified + * CoS queue ID will be arriving on this VNIC. Packet priority to CoS + * mapping rules can be specified using HWRM_QUEUE_PRI2COS_CFG. In this + * mode, ntuple filters with VNIC destination specified are invalid + * since they conflict with the CoS to VNIC steering rules in this + * mode. * * If this field is not specified, packet to VNIC steering will be * subject to the standard L2 filter rules and any additional ntuple @@ -35311,7 +40694,7 @@ typedef struct hwrm_vnic_cfg_input { * the number of header groups in the delivered packet with a valid * L4 checksum are reported. Valid checksums are counted from the * outermost header group to the innermost header group, stopping at - * the first error. This is the default checksum mode supported if + * the first error. This is the default checksum mode supported if * the driver doesn't explicitly configure the RX checksum mode. */ #define HWRM_VNIC_CFG_INPUT_RX_CSUM_V2_MODE_DEFAULT UINT32_C(0x0) @@ -35377,9 +40760,9 @@ typedef struct hwrm_vnic_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -35448,12 +40831,12 @@ typedef struct hwrm_vnic_qcfg_output { /* Default Completion ring for the VNIC. */ uint16_t dflt_ring_grp; /* - * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if + * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if * there is no RSS rule. */ uint16_t rss_rule; /* - * RSS ID for COS rule/table structure. 0xFF... (All Fs) if + * RSS ID for COS rule/table structure. 0xFF... (All Fs) if * there is no COS rule. */ uint16_t cos_rule; @@ -35533,9 +40916,9 @@ typedef struct hwrm_vnic_qcfg_output { /* When this bit is '1' it indicates port cos_mapping_mode enabled. */ #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_PORTCOS_MAPPING_MODE UINT32_C(0x100) /* - * When returned with a valid CoS Queue id, the CoS Queue/VNIC association - * is valid. Otherwise it will return 0xFFFF to indicate no VNIC/CoS - * queue association. + * When returned with a valid CoS Queue id, the CoS Queue/VNIC + * association is valid. Otherwise it will return 0xFFFF to indicate no + * VNIC/CoS queue association. */ uint16_t queue_id; /* @@ -35553,7 +40936,7 @@ typedef struct hwrm_vnic_qcfg_output { #define HWRM_VNIC_QCFG_OUTPUT_RX_CSUM_V2_MODE_DEFAULT UINT32_C(0x0) /* * This value indicates that the VNIC is configured to use the RX - * checksum ‘all_ok’ mode for all the rings associated with this + * checksum 'all_ok' mode for all the rings associated with this * VNIC. */ #define HWRM_VNIC_QCFG_OUTPUT_RX_CSUM_V2_MODE_ALL_OK UINT32_C(0x1) @@ -35586,12 +40969,33 @@ typedef struct hwrm_vnic_qcfg_output { */ #define HWRM_VNIC_QCFG_OUTPUT_L2_CQE_MODE_MIXED UINT32_C(0x2) #define HWRM_VNIC_QCFG_OUTPUT_L2_CQE_MODE_LAST HWRM_VNIC_QCFG_OUTPUT_L2_CQE_MODE_MIXED - uint8_t unused_1[3]; + /* + * This field conveys the metadata format type that has been + * configured. This value is product specific. Refer to the L2 HSI + * completion ring structures for the detailed descriptions. For Thor + * and Thor2, it corresponds to 'meta_format' in 'rx_pkt_cmpl_hi' and + * 'rx_pkt_v3_cmpl_hi', respectively. + */ + uint8_t metadata_format_type; + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_0 UINT32_C(0x0) + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_1 UINT32_C(0x1) + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_2 UINT32_C(0x2) + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_3 UINT32_C(0x3) + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_4 UINT32_C(0x4) + #define HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_LAST HWRM_VNIC_QCFG_OUTPUT_METADATA_FORMAT_TYPE_4 + /* This field conveys the VNIC operation state. */ + uint8_t vnic_state; + /* Normal operation state. */ + #define HWRM_VNIC_QCFG_OUTPUT_VNIC_STATE_NORMAL UINT32_C(0x0) + /* Drop all packets. */ + #define HWRM_VNIC_QCFG_OUTPUT_VNIC_STATE_DROP UINT32_C(0x1) + #define HWRM_VNIC_QCFG_OUTPUT_VNIC_STATE_LAST HWRM_VNIC_QCFG_OUTPUT_VNIC_STATE_DROP + uint8_t unused_1; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -35710,10 +41114,10 @@ typedef struct hwrm_vnic_qcaps_output { /* * When this bit is '1', it indicates that firmware supports the * ability to steer incoming packets from one CoS queue to one - * VNIC. This optional feature can then be enabled - * using HWRM_VNIC_CFG on any VNIC. This feature is only - * available when NVM option “enable_cos_classification” is set - * to 1. If set to '0', firmware does not support this feature. + * VNIC. This optional feature can then be enabled + * using HWRM_VNIC_CFG on any VNIC. This feature is only + * available when NVM option 'enable_cos_classification' is set + * to 1. If set to '0', firmware does not support this feature. */ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_COS_ASSIGNMENT_CAP UINT32_C(0x100) /* @@ -35771,8 +41175,8 @@ typedef struct hwrm_vnic_qcaps_output { #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RING_SELECT_MODE_TOEPLITZ_CAP UINT32_C(0x8000) /* * When this bit is '1', it indicates that HW is capable of using - * XOR algorithm. This mode uses XOR algorithm to hash the packets - * according to the configured hash type and hash mode. The XOR + * XOR algorithm. This mode uses 'XOR' algorithm to hash the packets + * according to the configured hash type and hash mode. The XOR * hash results and the provided XOR RSS indirection table are * used to determine the RSS rings. Host drivers provided hash key * is not honored in this mode. @@ -35785,7 +41189,7 @@ typedef struct hwrm_vnic_qcaps_output { * algorithm to calculate the hash to convey it in the RX * completions. Host drivers should provide Toeplitz hash key. * As HW uses innermost packets checksum to distribute the packets - * across the rings, host drivers can't convey hash mode to choose + * across the rings, host drivers can't convey hash mode to choose * outer headers to calculate Toeplitz hash. FW will fail such * configuration. */ @@ -35848,6 +41252,8 @@ typedef struct hwrm_vnic_qcaps_output { #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RSS_PROF_TCAM_MODE_ENABLED UINT32_C(0x8000000) /* When this bit is '1' FW supports VNIC hash mode. */ #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_VNIC_RSS_HASH_MODE_CAP UINT32_C(0x10000000) + /* When this bit is set to '1', hardware supports tunnel TPA. */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_HW_TUNNEL_TPA_CAP UINT32_C(0x20000000) /* * This field advertises the maximum concurrent TPA aggregations * supported by the VNIC on new devices that support TPA v2 or v3. @@ -35857,9 +41263,9 @@ typedef struct hwrm_vnic_qcaps_output { uint8_t unused_1[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -35870,7 +41276,7 @@ typedef struct hwrm_vnic_qcaps_output { *********************/ -/* hwrm_vnic_tpa_cfg_input (size:320b/40B) */ +/* hwrm_vnic_tpa_cfg_input (size:384b/48B) */ typedef struct hwrm_vnic_tpa_cfg_input { /* The HWRM command request type. */ @@ -35982,8 +41388,13 @@ typedef struct hwrm_vnic_tpa_cfg_input { * configured. */ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER UINT32_C(0x4) - /* deprecated bit. Do not use!!! */ + /* deprecated bit. Do not use!!! */ #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN UINT32_C(0x8) + /* + * This bit must be '1' for the tnl_tpa_en_bitmap field to be + * configured. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_TNL_TPA_EN UINT32_C(0x10) /* Logical vnic ID */ uint16_t vnic_id; /* @@ -36034,10 +41445,104 @@ typedef struct hwrm_vnic_tpa_cfg_input { /* * This is the minimum amount of payload length required to * start an aggregation context. This field is deprecated and - * should be set to 0. The minimum length is set by firmware + * should be set to 0. The minimum length is set by firmware * and can be queried using hwrm_vnic_tpa_qcfg. */ uint32_t min_agg_len; + /* + * If the device supports hardware tunnel TPA feature, as indicated by + * the HWRM_VNIC_QCAPS command, this field is used to configure the + * tunnel types to be enabled. Each bit corresponds to a specific + * tunnel type. If a bit is set to '1', then the associated tunnel + * type is enabled; otherwise, it is disabled. + */ + uint32_t tnl_tpa_en_bitmap; + /* + * When this bit is '1', enable VXLAN encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_VXLAN UINT32_C(0x1) + /* + * When this bit is set to '1', enable GENEVE encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_GENEVE UINT32_C(0x2) + /* + * When this bit is set to '1', enable NVGRE encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_NVGRE UINT32_C(0x4) + /* + * When this bit is set to '1', enable GRE encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_GRE UINT32_C(0x8) + /* + * When this bit is set to '1', enable IPV4 encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_IPV4 UINT32_C(0x10) + /* + * When this bit is set to '1', enable IPV6 encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_IPV6 UINT32_C(0x20) + /* + * When this bit is '1', enable VXLAN_GPE encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_VXLAN_GPE UINT32_C(0x40) + /* + * When this bit is '1', enable VXLAN_CUSTOMER1 encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_VXLAN_CUST1 UINT32_C(0x80) + /* + * When this bit is '1', enable GRE_CUSTOMER1 encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_GRE_CUST1 UINT32_C(0x100) + /* + * When this bit is '1', enable UPAR1 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR1 UINT32_C(0x200) + /* + * When this bit is '1', enable UPAR2 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR2 UINT32_C(0x400) + /* + * When this bit is '1', enable UPAR3 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR3 UINT32_C(0x800) + /* + * When this bit is '1', enable UPAR4 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR4 UINT32_C(0x1000) + /* + * When this bit is '1', enable UPAR5 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR5 UINT32_C(0x2000) + /* + * When this bit is '1', enable UPAR6 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR6 UINT32_C(0x4000) + /* + * When this bit is '1', enable UPAR7 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR7 UINT32_C(0x8000) + /* + * When this bit is '1', enable UPAR8 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_TNL_TPA_EN_BITMAP_UPAR8 UINT32_C(0x10000) + uint8_t unused_1[4]; } hwrm_vnic_tpa_cfg_input_t, *phwrm_vnic_tpa_cfg_input_t; /* hwrm_vnic_tpa_cfg_output (size:128b/16B) */ @@ -36054,9 +41559,9 @@ typedef struct hwrm_vnic_tpa_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -36215,12 +41720,105 @@ typedef struct hwrm_vnic_tpa_qcfg_output { * start an aggregation context. */ uint32_t min_agg_len; - uint8_t unused_0[7]; + /* + * If the device supports hardware tunnel TPA feature, as indicated by + * the HWRM_VNIC_QCAPS command, this field conveys the bitmap of the + * tunnel types that have been configured. Each bit corresponds to a + * specific tunnel type. If a bit is set to '1', then the associated + * tunnel type is enabled; otherwise, it is disabled. + */ + uint32_t tnl_tpa_en_bitmap; + /* + * When this bit is '1', enable VXLAN encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_VXLAN UINT32_C(0x1) + /* + * When this bit is set to '1', enable GENEVE encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_GENEVE UINT32_C(0x2) + /* + * When this bit is set to '1', enable NVGRE encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_NVGRE UINT32_C(0x4) + /* + * When this bit is set to '1', enable GRE encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_GRE UINT32_C(0x8) + /* + * When this bit is set to '1', enable IPV4 encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_IPV4 UINT32_C(0x10) + /* + * When this bit is set to '1', enable IPV6 encapsulated packets + * for aggregation.. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_IPV6 UINT32_C(0x20) + /* + * When this bit is '1', enable VXLAN_GPE encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_VXLAN_GPE UINT32_C(0x40) + /* + * When this bit is '1', enable VXLAN_CUSTOMER1 encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_VXLAN_CUST1 UINT32_C(0x80) + /* + * When this bit is '1', enable GRE_CUSTOMER1 encapsulated packets + * for aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_GRE_CUST1 UINT32_C(0x100) + /* + * When this bit is '1', enable UPAR1 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR1 UINT32_C(0x200) + /* + * When this bit is '1', enable UPAR2 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR2 UINT32_C(0x400) + /* + * When this bit is '1', enable UPAR3 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR3 UINT32_C(0x800) + /* + * When this bit is '1', enable UPAR4 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR4 UINT32_C(0x1000) + /* + * When this bit is '1', enable UPAR5 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR5 UINT32_C(0x2000) + /* + * When this bit is '1', enable UPAR6 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR6 UINT32_C(0x4000) + /* + * When this bit is '1', enable UPAR7 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR7 UINT32_C(0x8000) + /* + * When this bit is '1', enable UPAR8 encapsulated packets for + * aggregation. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_TNL_TPA_EN_BITMAP_UPAR8 UINT32_C(0x10000) + uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -36413,7 +42011,7 @@ typedef struct hwrm_vnic_rss_cfg_input { * specified headers. It is an error to set this flag concurrently * with hash_type_exclude. */ - #define HWRM_VNIC_RSS_CFG_INPUT_FLAGS_HASH_TYPE_INCLUDE UINT32_C(0x1) + #define HWRM_VNIC_RSS_CFG_INPUT_FLAGS_HASH_TYPE_INCLUDE UINT32_C(0x1) /* * When this bit is '1', it indicates that the hash_type field is * interpreted as a change relative the current configuration. Each @@ -36425,7 +42023,12 @@ typedef struct hwrm_vnic_rss_cfg_input { * remove the specified headers. It is an error to set this flag * concurrently with hash_type_include. */ - #define HWRM_VNIC_RSS_CFG_INPUT_FLAGS_HASH_TYPE_EXCLUDE UINT32_C(0x2) + #define HWRM_VNIC_RSS_CFG_INPUT_FLAGS_HASH_TYPE_EXCLUDE UINT32_C(0x2) + /* + * When this bit is '1', it indicates that the support of setting + * ipsec hash_types by the host drivers. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT UINT32_C(0x4) uint8_t ring_select_mode; /* * In this mode, HW uses Toeplitz algorithm and provided Toeplitz @@ -36471,9 +42074,9 @@ typedef struct hwrm_vnic_rss_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -36714,9 +42317,9 @@ typedef struct hwrm_vnic_rss_qcfg_output { uint8_t unused_1[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -36896,7 +42499,7 @@ typedef struct hwrm_vnic_plcmodes_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -37041,7 +42644,7 @@ typedef struct hwrm_vnic_plcmodes_qcfg_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -37104,9 +42707,9 @@ typedef struct hwrm_vnic_rss_cos_lb_ctx_alloc_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -37167,9 +42770,9 @@ typedef struct hwrm_vnic_rss_cos_lb_ctx_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -37252,6 +42855,11 @@ typedef struct hwrm_ring_alloc_input { * configured. */ #define HWRM_RING_ALLOC_INPUT_ENABLES_MPC_CHNLS_TYPE UINT32_C(0x400) + /* + * This bit must be '1' for the steering_tag field to be + * configured. + */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_STEERING_TAG_VALID UINT32_C(0x800) /* Ring Type. */ uint8_t ring_type; /* L2 Completion Ring (CR) */ @@ -37388,7 +42996,7 @@ typedef struct hwrm_ring_alloc_input { /* Used by a PF driver to associate a SCHQ with one of its TX rings. */ uint16_t schq_id; /* - * Number of 16B units in the ring. Minimum size for + * Number of 16B units in the ring. Minimum size for * a ring is 16 16B entries. */ uint32_t length; @@ -37465,7 +43073,8 @@ typedef struct hwrm_ring_alloc_input { */ #define HWRM_RING_ALLOC_INPUT_RING_ARB_CFG_ARB_POLICY_PARAM_MASK UINT32_C(0xff00) #define HWRM_RING_ALLOC_INPUT_RING_ARB_CFG_ARB_POLICY_PARAM_SFT 8 - uint16_t unused_3; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; /* * This field is reserved for the future use. * It shall be set to 0. @@ -37601,9 +43210,9 @@ typedef struct hwrm_ring_alloc_output { uint8_t unused_0[2]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -37706,9 +43315,9 @@ typedef struct hwrm_ring_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -37761,7 +43370,7 @@ typedef struct hwrm_ring_reset_input { /* RoCE Notification Completion Ring (ROCE_CR) */ #define HWRM_RING_RESET_INPUT_RING_TYPE_ROCE_CMPL UINT32_C(0x3) /* - * Rx Ring Group. This is to reset rx and aggregation in an atomic + * Rx Ring Group. This is to reset rx and aggregation in an atomic * operation. Completion ring associated with this ring group is * not reset. */ @@ -37802,9 +43411,9 @@ typedef struct hwrm_ring_reset_output { uint8_t consumer_idx[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -37957,7 +43566,7 @@ typedef struct hwrm_ring_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -38097,7 +43706,7 @@ typedef struct hwrm_ring_qcfg_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -38182,8 +43791,8 @@ typedef struct hwrm_ring_aggint_qcaps_output { */ #define HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_NUM_CMPL_DMA_AGGR UINT32_C(0x10) /* - * When this bit is set to '1', num_cmpl_dma_aggr_during_int can be configured - * on completion rings. + * When this bit is set to '1', num_cmpl_dma_aggr_during_int can be + * configured on completion rings. */ #define HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_NUM_CMPL_DMA_AGGR_DURING_INT UINT32_C(0x20) /* @@ -38192,8 +43801,8 @@ typedef struct hwrm_ring_aggint_qcaps_output { */ #define HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_CMPL_AGGR_DMA_TMR UINT32_C(0x40) /* - * When this bit is set to '1', cmpl_aggr_dma_tmr_during_int can be configured - * on completion rings. + * When this bit is set to '1', cmpl_aggr_dma_tmr_during_int can be + * configured on completion rings. */ #define HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_CMPL_AGGR_DMA_TMR_DURING_INT UINT32_C(0x80) /* @@ -38240,9 +43849,9 @@ typedef struct hwrm_ring_aggint_qcaps_output { uint8_t unused_0[1]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -38356,9 +43965,9 @@ typedef struct hwrm_ring_cmpl_ring_qaggint_params_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -38465,8 +44074,8 @@ typedef struct hwrm_ring_cmpl_ring_cfg_aggint_params_input { */ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_ENABLES_NUM_CMPL_DMA_AGGR UINT32_C(0x1) /* - * This bit must be '1' for the num_cmpl_dma_aggr_during_int field to be - * configured. + * This bit must be '1' for the num_cmpl_dma_aggr_during_int field to + * be configured. */ #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_ENABLES_NUM_CMPL_DMA_AGGR_DURING_INT UINT32_C(0x2) /* @@ -38506,9 +44115,9 @@ typedef struct hwrm_ring_cmpl_ring_cfg_aggint_params_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -38562,7 +44171,7 @@ typedef struct hwrm_ring_grp_alloc_input { uint16_t rr; /* * This value identifies the aggregation RR associated with - * the ring group. If this value is 0xFF... (All Fs), then no + * the ring group. If this value is 0xFF... (All Fs), then no * Aggregation ring will be set. */ uint16_t ar; @@ -38585,7 +44194,7 @@ typedef struct hwrm_ring_grp_alloc_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * This is the ring group ID value. Use this value to program + * This is the ring group ID value. Use this value to program * the default ring group for the VNIC or as table entries * in an RSS/COS context. */ @@ -38593,9 +44202,9 @@ typedef struct hwrm_ring_grp_alloc_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -38656,9 +44265,9 @@ typedef struct hwrm_ring_grp_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -39128,9 +44737,9 @@ typedef struct hwrm_ring_schq_alloc_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -39187,8 +44796,8 @@ typedef struct hwrm_ring_schq_cfg_input { uint32_t flags; /* The tc_max_bw array and the max_bw parameters are valid */ #define HWRM_RING_SCHQ_CFG_INPUT_FLAGS_TC_MAX_BW_ENABLED UINT32_C(0x1) - /* The tc_min_bw array is valid */ - #define HWRM_RING_SCHQ_CFG_INPUT_FLAGS_TC_MIN_BW_ENABLED UINT32_C(0x2) + /* The tc_bw_reservation array is valid */ + #define HWRM_RING_SCHQ_CFG_INPUT_FLAGS_TC_RESERVATION_ENABLED UINT32_C(0x2) /* Maximum bandwidth of the traffic class, specified in Mbps. */ uint32_t max_bw_tc0; /* Maximum bandwidth of the traffic class, specified in Mbps. */ @@ -39206,61 +44815,61 @@ typedef struct hwrm_ring_schq_cfg_input { /* Maximum bandwidth of the traffic class, specified in Mbps. */ uint32_t max_bw_tc7; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc0; + uint32_t tc_bw_reservation0; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc1; + uint32_t tc_bw_reservation1; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc2; + uint32_t tc_bw_reservation2; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc3; + uint32_t tc_bw_reservation3; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc4; + uint32_t tc_bw_reservation4; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc5; + uint32_t tc_bw_reservation5; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc6; + uint32_t tc_bw_reservation6; /* - * Bandwidth reservation for the traffic class, specified in Mbps. + * Bandwidth reservation for the traffic class, specified in percent. * A value of zero signifies that traffic belonging to this class * shares the bandwidth reservation for the same traffic class of * the default SCHQ. */ - uint32_t min_bw_tc7; + uint32_t tc_bw_reservation7; /* * Indicates the max bandwidth for all enabled traffic classes in * this SCHQ, specified in Mbps. @@ -39283,9 +44892,9 @@ typedef struct hwrm_ring_schq_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -39346,9 +44955,9 @@ typedef struct hwrm_ring_schq_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -39874,7 +45483,7 @@ typedef struct hwrm_cfa_l2_filter_free_output { **************************/ -/* hwrm_cfa_l2_filter_cfg_input (size:320b/40B) */ +/* hwrm_cfa_l2_filter_cfg_input (size:384b/48B) */ typedef struct hwrm_cfa_l2_filter_cfg_input { /* The HWRM command request type. */ @@ -39916,7 +45525,7 @@ typedef struct hwrm_cfa_l2_filter_cfg_input { #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) /* rx path */ #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) - #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX /* * Setting of this flag indicates drop action. If this flag is not * set, then it should be considered accept action. @@ -39929,12 +45538,30 @@ typedef struct hwrm_cfa_l2_filter_cfg_input { #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_MASK UINT32_C(0xc) #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_SFT 2 /* To support old drivers */ - #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_NO_ROCE_L2 (UINT32_C(0x0) << 2) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_NO_ROCE_L2 (UINT32_C(0x0) << 2) /* Only L2 traffic */ - #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_L2 (UINT32_C(0x1) << 2) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_L2 (UINT32_C(0x1) << 2) /* Roce & L2 traffic */ - #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_ROCE (UINT32_C(0x2) << 2) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_ROCE (UINT32_C(0x2) << 2) #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_TRAFFIC_ROCE + /* + * Enumeration denoting how the L2 Context TCAM remap operation is + * updated. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_MASK UINT32_C(0x30) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_SFT 4 + /* No change to remap opcode */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_NO_UPDATE (UINT32_C(0x0) << 4) + /* Bypass CFA Lookup */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_BYPASS_LKUP (UINT32_C(0x1) << 4) + /* Enable CFA Lookup */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_ENABLE_LKUP (UINT32_C(0x2) << 4) + /* + * Restore the remap opcode originally programmed by firmware flow + * manager + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_RESTORE_FW_OP (UINT32_C(0x3) << 4) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_REMAP_OP_RESTORE_FW_OP uint32_t enables; /* * This bit must be '1' for the dst_id field to be @@ -39947,6 +45574,16 @@ typedef struct hwrm_cfa_l2_filter_cfg_input { */ #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2) /* + * This bit must be '1' for the prof_func field to be configured in + * the remap entry. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_PROF_FUNC UINT32_C(0x4) + /* + * This bit must be '1' for the l2_context_id field to be configured + * in the remap entry. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_L2_CONTEXT_ID UINT32_C(0x8) + /* * This value identifies a set of CFA data structures used for an L2 * context. */ @@ -39963,6 +45600,22 @@ typedef struct hwrm_cfa_l2_filter_cfg_input { * mirrored. */ uint32_t new_mirror_vnic_id; + /* + * Profile function value to be programmed into the L2 context entry's + * remap. This will be used by the host application to program the CFA + * Profile TCAM entry for further classification. A value of 0xFFFFFFFF + * indicates that the profile function should be restored to the value + * originally programmed by the firmware flow manager. + */ + uint32_t prof_func; + /* + * L2 context ID value to be programmed into the L2 context entry's + * remap. This will be used by the host application to program the CFA + * Lookup entry for further classification. A value of 0xFFFFFFFF + * indicates that the profile function should be restored to the value + * originally programmed by the firmware flow manager. + */ + uint32_t l2_context_id; } hwrm_cfa_l2_filter_cfg_input_t, *phwrm_cfa_l2_filter_cfg_input_t; /* hwrm_cfa_l2_filter_cfg_output (size:128b/16B) */ @@ -41358,13 +47011,16 @@ typedef struct hwrm_cfa_ntuple_filter_alloc_input { /* * Setting of this flag indicates that the dst_id field contains RFS * ring table index. If this is not set it indicates dst_id is VNIC - * or VPORT or function ID. Note dest_fid and dest_rfs_ring_idx - * can’t be set at the same time. + * or VPORT or function ID. Note dest_fid and dest_rfs_ring_idx + * can't be set at the same time. Updated drivers should pass ring + * idx in the rfs_ring_tbl_idx field if the firmware indicates + * support for the new field in the HWRM_CFA_ADV_FLOW_MGMT_QCAPS + * response. */ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_DEST_RFS_RING_IDX UINT32_C(0x20) /* * Setting of this flag indicates that when the ntuple filter is - * created, the L2 context should not be used in the filter. This + * created, the L2 context should not be used in the filter. This * allows packet from different L2 contexts to match and be directed * to the same destination. */ @@ -41455,17 +47111,17 @@ typedef struct hwrm_cfa_ntuple_filter_alloc_input { * configured. */ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x10000) - /* - * This bit must be '1' for the mirror_vnic_id field to be - * configured. - */ + /* This flag is deprecated. */ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x20000) /* * This bit must be '1' for the dst_macaddr field to be * configured. */ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_MACADDR UINT32_C(0x40000) - /* This flag is deprecated. */ + /* + * This bit must be '1' for the rfs_ring_tbl_idx field to + * be configured. + */ #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_RFS_RING_TBL_IDX UINT32_C(0x80000) /* * This value identifies a set of CFA data structures used for an L2 @@ -41494,7 +47150,7 @@ typedef struct hwrm_cfa_ntuple_filter_alloc_input { #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_LAST HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 /* - * The value of protocol filed in IP header. + * The value of protocol field in IP header. * Applies to UDP and TCP traffic. * 6 - TCP * 17 - UDP @@ -41524,10 +47180,12 @@ typedef struct hwrm_cfa_ntuple_filter_alloc_input { */ uint16_t dst_id; /* - * Logical VNIC ID of the VNIC where traffic is - * mirrored. + * If set, this value shall represent the ring table + * index for receive flow steering. Note that this offset + * was formerly used for the mirror_vnic_id field, which + * is no longer supported. */ - uint16_t mirror_vnic_id; + uint16_t rfs_ring_tbl_idx; /* * This value indicates the tunnel type for this filter. * If this field is not specified, then the filter shall @@ -41837,13 +47495,13 @@ typedef struct hwrm_cfa_ntuple_filter_cfg_input { /* * Setting of this flag indicates that the new_dst_id field contains * RFS ring table index. If this is not set it indicates new_dst_id - * is VNIC or VPORT or function ID. Note dest_fid and - * dest_rfs_ring_idx can’t be set at the same time. + * is VNIC or VPORT or function ID. Note dest_fid and + * dest_rfs_ring_idx can't be set at the same time. */ #define HWRM_CFA_NTUPLE_FILTER_CFG_INPUT_FLAGS_DEST_RFS_RING_IDX UINT32_C(0x2) /* * Setting of this flag indicates that when the ntuple filter is - * created, the L2 context should not be used in the filter. This + * created, the L2 context should not be used in the filter. This * allows packet from different L2 contexts to match and be directed * to the same destination. */ @@ -42168,7 +47826,7 @@ typedef struct hwrm_cfa_em_flow_alloc_input { #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_LAST HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 /* - * The value of protocol filed in IP header. + * The value of protocol field in IP header. * Applies to UDP and TCP traffic. * 6 - TCP * 17 - UDP @@ -43548,7 +49206,7 @@ typedef struct hwrm_cfa_decap_filter_alloc_input { #define HWRM_CFA_DECAP_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) #define HWRM_CFA_DECAP_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_LAST HWRM_CFA_DECAP_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 /* - * The value of protocol filed in IP header. + * The value of protocol field in IP header. * Applies to UDP and TCP traffic. * 6 - TCP * 17 - UDP @@ -44749,7 +50407,7 @@ typedef struct hwrm_cfa_flow_stats_output { * If a flow has been hit, the bit representing the flow will be 1. * Likewise, if a flow has not, the bit representing the flow * will be 0. Mapping will match flow numbers where bitX is for flowX - * (ex: bit 0 is flow0). This only applies for NIC flows. Upon + * (ex: bit 0 is flow0). This only applies for NIC flows. Upon * reading of the flow, the bit will be cleared for the flow and only * set again when traffic is received by the flow. */ @@ -46954,7 +52612,7 @@ typedef struct hwrm_cfa_eem_qcaps_output { /* * When set to 1, indicates the FW supports the Centralized * Memory Model. The concept designates one entity for the - * memory allocation while all others ‘subscribe’ to it. + * memory allocation while all others 'subscribe' to it. */ #define HWRM_CFA_EEM_QCAPS_OUTPUT_FLAGS_CENTRALIZED_MEMORY_MODEL_SUPPORTED UINT32_C(0x4) /* @@ -47490,10 +53148,16 @@ typedef struct hwrm_cfa_adv_flow_mgnt_qcaps_output { #define HWRM_CFA_ADV_FLOW_MGNT_QCAPS_OUTPUT_FLAGS_NIC_FLOW_STATS_SUPPORTED UINT32_C(0x80000) /* * If set to 1, firmware is capable of supporting these additional - * ip_protoccols: ICMP, ICMPV6, RSVD for ntuple rules. By default, + * ip_protocols: ICMP, ICMPV6, RSVD for ntuple rules. By default, * this flag should be 0 for older version of firmware. */ #define HWRM_CFA_ADV_FLOW_MGNT_QCAPS_OUTPUT_FLAGS_NTUPLE_FLOW_RX_EXT_IP_PROTO_SUPPORTED UINT32_C(0x100000) + /* + * Value of 1 to indicate that firmware supports setting of + * rfs_ring_tbl_idx (new offset) in HWRM_CFA_NTUPLE_ALLOC command. + * Value of 0 indicates ring tbl idx should be passed using dst_id. + */ + #define HWRM_CFA_ADV_FLOW_MGNT_QCAPS_OUTPUT_FLAGS_RFS_RING_TBL_IDX_V3_SUPPORTED UINT32_C(0x200000) uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output @@ -47629,7 +53293,7 @@ typedef struct hwrm_cfa_lag_group_member_rgtr_input { /* * Transmit based on packet header ntuple hash. Packet with only * layer 2 headers will hash using the destination MAC, source MAC - * and Ethertype fields. Packets with layer 3 (IP) headers will + * and Ethertype fields. Packets with layer 3 (IP) headers will * hash using the destination MAC, source MAC, IP protocol/next * header, source IP address and destination IP address. Packets * with layer 4 (TCP/UDP) headers will hash using the destination @@ -47744,7 +53408,7 @@ typedef struct hwrm_cfa_lag_group_member_unrgtr_output { *****************************/ -/* hwrm_cfa_tls_filter_alloc_input (size:704b/88B) */ +/* hwrm_cfa_tls_filter_alloc_input (size:768b/96B) */ typedef struct hwrm_cfa_tls_filter_alloc_input { /* The HWRM command request type. */ @@ -47781,47 +53445,47 @@ typedef struct hwrm_cfa_tls_filter_alloc_input { * This bit must be '1' for the l2_filter_id field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1) /* * This bit must be '1' for the ethertype field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x2) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x2) /* * This bit must be '1' for the ipaddr_type field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x4) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x4) /* * This bit must be '1' for the src_ipaddr field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x8) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x8) /* * This bit must be '1' for the dst_ipaddr field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x10) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x10) /* * This bit must be '1' for the ip_protocol field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x20) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x20) /* * This bit must be '1' for the src_port field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x40) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x40) /* * This bit must be '1' for the dst_port field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x80) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x80) /* * This bit must be '1' for the kid field to be * configured. */ - #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_KID UINT32_C(0x100) + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_KID UINT32_C(0x100) /* * This bit must be '1' for the dst_id field to be * configured. @@ -47833,6 +53497,11 @@ typedef struct hwrm_cfa_tls_filter_alloc_input { */ #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x400) /* + * This bit must be '1' for the quic_dst_connect_id field to be + * configured. + */ + #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_ENABLES_QUIC_DST_CONNECT_ID UINT32_C(0x800) + /* * This value identifies a set of CFA data structures used for an L2 * context. */ @@ -47855,7 +53524,7 @@ typedef struct hwrm_cfa_tls_filter_alloc_input { #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) #define HWRM_CFA_TLS_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_LAST HWRM_CFA_TLS_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 /* - * The value of protocol filed in IP header. + * The value of protocol field in IP header. * Applies to UDP and TCP traffic. * 6 - TCP * 17 - UDP @@ -47902,10 +53571,12 @@ typedef struct hwrm_cfa_tls_filter_alloc_input { */ uint16_t dst_port; /* - * The Key Context Identifier (KID) for use with KTLS. + * The Key Context Identifier (KID) for use with KTLS or QUIC. * KID is limited to 20-bits. */ uint32_t kid; + /* The Destination Connection ID of QUIC. */ + uint64_t quic_dst_connect_id; } hwrm_cfa_tls_filter_alloc_input_t, *phwrm_cfa_tls_filter_alloc_input_t; /* hwrm_cfa_tls_filter_alloc_output (size:192b/24B) */ @@ -48027,6 +53698,93 @@ typedef struct hwrm_cfa_tls_filter_free_output { uint8_t valid; } hwrm_cfa_tls_filter_free_output_t, *phwrm_cfa_tls_filter_free_output_t; +/***************************** + * hwrm_cfa_release_afm_func * + *****************************/ + + +/* hwrm_cfa_release_afm_func_input (size:256b/32B) */ + +typedef struct hwrm_cfa_release_afm_func_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Function identifier, may be of type efid, rfid or dfid. */ + uint16_t fid; + /* Representor function identifier. */ + uint16_t rfid; + /* Fid type. */ + uint8_t type; + /* Endpoint fid. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_EFID UINT32_C(0x1) + /* Representor fid. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_RFID UINT32_C(0x2) + /* Redirect fid. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_DFID UINT32_C(0x3) + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_LAST HWRM_CFA_RELEASE_AFM_FUNC_INPUT_TYPE_DFID + uint8_t unused_0[3]; + /* + * Flags used to control AFMs actions when releasing the function. + * Only used when type is dfid. + */ + uint32_t flags; + /* Remove broadcast. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_FLAGS_BC_REM UINT32_C(0x1) + /* Remove multicast. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_FLAGS_MC_REM UINT32_C(0x2) + /* Remove promiscuous. */ + #define HWRM_CFA_RELEASE_AFM_FUNC_INPUT_FLAGS_PROMISC_REM UINT32_C(0x4) + uint32_t unused_1; +} hwrm_cfa_release_afm_func_input_t, *phwrm_cfa_release_afm_func_input_t; + +/* hwrm_cfa_release_afm_func_output (size:128b/16B) */ + +typedef struct hwrm_cfa_release_afm_func_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field is + * written last. + */ + uint8_t valid; +} hwrm_cfa_release_afm_func_output_t, *phwrm_cfa_release_afm_func_output_t; + /*********** * hwrm_tf * ***********/ @@ -48098,7 +53856,7 @@ typedef struct hwrm_tf_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -48273,91 +54031,6 @@ typedef struct hwrm_tf_session_open_output { uint8_t valid; } hwrm_tf_session_open_output_t, *phwrm_tf_session_open_output_t; -/************************** - * hwrm_tf_session_attach * - **************************/ - - -/* hwrm_tf_session_attach_input (size:704b/88B) */ - -typedef struct hwrm_tf_session_attach_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* - * Unique session identifier for the session that the attach - * request want to attach to. This value originates from the - * shared session memory that the attach request opened by - * way of the 'attach name' that was passed in to the core - * attach API. - * The fw_session_id of the attach session includes PCIe bus - * info to distinguish the PF and session info to identify - * the associated TruFlow session. - */ - uint32_t attach_fw_session_id; - /* unused. */ - uint32_t unused0; - /* Name of the session it self. */ - uint8_t session_name[64]; -} hwrm_tf_session_attach_input_t, *phwrm_tf_session_attach_input_t; - -/* hwrm_tf_session_attach_output (size:128b/16B) */ - -typedef struct hwrm_tf_session_attach_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* - * Unique session identifier for the session created by the - * firmware. It includes PCIe bus info to distinguish the PF - * and session info to identify the associated TruFlow - * session. This fw_session_id is unique to the attach - * request. - */ - uint32_t fw_session_id; - /* unused. */ - uint8_t unused0[3]; - /* - * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal - * processor, the order of writes has to be such that this field is - * written last. - */ - uint8_t valid; -} hwrm_tf_session_attach_output_t, *phwrm_tf_session_attach_output_t; - /**************************** * hwrm_tf_session_register * ****************************/ @@ -48898,91 +54571,6 @@ typedef struct hwrm_tf_session_resc_alloc_output { uint8_t valid; } hwrm_tf_session_resc_alloc_output_t, *phwrm_tf_session_resc_alloc_output_t; -/***************************** - * hwrm_tf_session_resc_free * - *****************************/ - - -/* hwrm_tf_session_resc_free_input (size:256b/32B) */ - -typedef struct hwrm_tf_session_resc_free_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; - /* Control flags. */ - uint16_t flags; - /* Indicates the flow direction. */ - #define HWRM_TF_SESSION_RESC_FREE_INPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_SESSION_RESC_FREE_INPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_SESSION_RESC_FREE_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_SESSION_RESC_FREE_INPUT_FLAGS_DIR_LAST HWRM_TF_SESSION_RESC_FREE_INPUT_FLAGS_DIR_TX - /* - * Defines the size, in bytes, of the provided free_addr - * buffer. - */ - uint16_t free_size; - /* - * This is the DMA address for the free input data array - * buffer. Array is of tf_rm_resc_entry type. Size of the - * buffer is provided by the 'free_size' field of this - * message. - */ - uint64_t free_addr; -} hwrm_tf_session_resc_free_input_t, *phwrm_tf_session_resc_free_input_t; - -/* hwrm_tf_session_resc_free_output (size:128b/16B) */ - -typedef struct hwrm_tf_session_resc_free_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* unused. */ - uint8_t unused0[7]; - /* - * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal - * processor, the order of writes has to be such that this field is - * written last. - */ - uint8_t valid; -} hwrm_tf_session_resc_free_output_t, *phwrm_tf_session_resc_free_output_t; - /****************************** * hwrm_tf_session_resc_flush * ******************************/ @@ -49037,7 +54625,7 @@ typedef struct hwrm_tf_session_resc_flush_input { uint16_t flush_size; /* * This is the DMA address for the flush input data array - * buffer. Array of tf_rm_resc_entry type. Size of the + * buffer. Array of tf_rm_resc_entry type. Size of the * buffer is provided by the 'flush_size' field in this * message. */ @@ -49192,14 +54780,14 @@ typedef struct tf_rm_resc_entry { uint16_t stride; } tf_rm_resc_entry_t, *ptf_rm_resc_entry_t; -/************************ - * hwrm_tf_tbl_type_get * - ************************/ +/************************** + * hwrm_tf_tbl_type_alloc * + **************************/ -/* hwrm_tf_tbl_type_get_input (size:256b/32B) */ +/* hwrm_tf_tbl_type_alloc_input (size:192b/24B) */ -typedef struct hwrm_tf_tbl_type_get_input { +typedef struct hwrm_tf_tbl_type_alloc_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -49233,31 +54821,34 @@ typedef struct hwrm_tf_tbl_type_get_input { /* Control flags. */ uint16_t flags; /* Indicates the flow direction. */ - #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_FLAGS_DIR UINT32_C(0x1) /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_FLAGS_DIR_RX UINT32_C(0x0) /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_TX - /* - * When set use the special access register access to clear - * the table entry on read. - */ - #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_CLEAR_ON_READ UINT32_C(0x2) - /* unused. */ - uint8_t unused0[2]; - /* - * Type of the resource, defined globally in the - * hwrm_tf_resc_type enum. + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_ALLOC_INPUT_FLAGS_DIR_TX + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_LAST HWRM_TF_TBL_TYPE_ALLOC_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE + /* + * This field is blktype specific. For any of the UPAR types it is + * set to a non-zero value in case of a re-alloc, specifies a + * tunnel-type of dynamic UPAR tunnel. */ - uint32_t type; - /* Index of the type to retrieve. */ - uint32_t index; -} hwrm_tf_tbl_type_get_input_t, *phwrm_tf_tbl_type_get_input_t; + uint8_t type; +} hwrm_tf_tbl_type_alloc_input_t, *phwrm_tf_tbl_type_alloc_input_t; -/* hwrm_tf_tbl_type_get_output (size:2240b/280B) */ +/* hwrm_tf_tbl_type_alloc_output (size:128b/16B) */ -typedef struct hwrm_tf_tbl_type_get_output { +typedef struct hwrm_tf_tbl_type_alloc_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -49268,14 +54859,13 @@ typedef struct hwrm_tf_tbl_type_get_output { uint16_t resp_len; /* Response code. */ uint32_t resp_code; - /* Response size. */ - uint16_t size; - /* unused */ - uint16_t unused0; - /* Response data. */ - uint8_t data[256]; + /* + * Table entry allocated by the firmware using the + * parameters above. + */ + uint16_t idx_tbl_id; /* unused */ - uint8_t unused1[7]; + uint8_t unused0; /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' @@ -49285,16 +54875,16 @@ typedef struct hwrm_tf_tbl_type_get_output { * is written last. */ uint8_t valid; -} hwrm_tf_tbl_type_get_output_t, *phwrm_tf_tbl_type_get_output_t; +} hwrm_tf_tbl_type_alloc_output_t, *phwrm_tf_tbl_type_alloc_output_t; /************************ - * hwrm_tf_tbl_type_set * + * hwrm_tf_tbl_type_get * ************************/ -/* hwrm_tf_tbl_type_set_input (size:1024b/128B) */ +/* hwrm_tf_tbl_type_get_input (size:256b/32B) */ -typedef struct hwrm_tf_tbl_type_set_input { +typedef struct hwrm_tf_tbl_type_get_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -49328,16 +54918,30 @@ typedef struct hwrm_tf_tbl_type_set_input { /* Control flags. */ uint16_t flags; /* Indicates the flow direction. */ - #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR UINT32_C(0x1) /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_TX - /* Indicate table data is being sent via DMA. */ - #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DMA UINT32_C(0x2) + #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_DIR_TX + /* + * When set use the special access register access to clear + * the table entry on read. + */ + #define HWRM_TF_TBL_TYPE_GET_INPUT_FLAGS_CLEAR_ON_READ UINT32_C(0x2) + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_LAST HWRM_TF_TBL_TYPE_GET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE /* unused. */ - uint8_t unused0[2]; + uint8_t unused0; /* * Type of the resource, defined globally in the * hwrm_tf_resc_type enum. @@ -49345,17 +54949,11 @@ typedef struct hwrm_tf_tbl_type_set_input { uint32_t type; /* Index of the type to retrieve. */ uint32_t index; - /* Size of the data to set. */ - uint16_t size; - /* unused */ - uint8_t unused1[6]; - /* Data to be set. */ - uint8_t data[88]; -} hwrm_tf_tbl_type_set_input_t, *phwrm_tf_tbl_type_set_input_t; +} hwrm_tf_tbl_type_get_input_t, *phwrm_tf_tbl_type_get_input_t; -/* hwrm_tf_tbl_type_set_output (size:128b/16B) */ +/* hwrm_tf_tbl_type_get_output (size:2240b/280B) */ -typedef struct hwrm_tf_tbl_type_set_output { +typedef struct hwrm_tf_tbl_type_get_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -49364,8 +54962,16 @@ typedef struct hwrm_tf_tbl_type_set_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* unused. */ - uint8_t unused0[7]; + /* Response code. */ + uint32_t resp_code; + /* Response size. */ + uint16_t size; + /* unused */ + uint16_t unused0; + /* Response data. */ + uint8_t data[256]; + /* unused */ + uint8_t unused1[7]; /* * This field is used in Output records to indicate that the output * is completely written to RAM. This field should be read as '1' @@ -49375,413 +54981,16 @@ typedef struct hwrm_tf_tbl_type_set_output { * is written last. */ uint8_t valid; -} hwrm_tf_tbl_type_set_output_t, *phwrm_tf_tbl_type_set_output_t; - -/************************** - * hwrm_tf_ctxt_mem_alloc * - **************************/ - - -/* hwrm_tf_ctxt_mem_alloc_input (size:192b/24B) */ - -typedef struct hwrm_tf_ctxt_mem_alloc_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Size in KB of memory to be allocated. */ - uint32_t mem_size; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; -} hwrm_tf_ctxt_mem_alloc_input_t, *phwrm_tf_ctxt_mem_alloc_input_t; - -/* hwrm_tf_ctxt_mem_alloc_output (size:192b/24B) */ - -typedef struct hwrm_tf_ctxt_mem_alloc_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* Pointer to the PBL, or PDL depending on number of levels */ - uint64_t page_dir; - /* Size of memory allocated. */ - uint32_t mem_size; - /* Counter PBL indirect levels. */ - uint8_t page_level; - /* PBL pointer is physical start address. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_LEVEL_LVL_0 UINT32_C(0x0) - /* PBL pointer points to PTE table. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_LEVEL_LVL_1 UINT32_C(0x1) - /* - * PBL pointer points to PDE table with each entry pointing - * to PTE tables. - */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_LEVEL_LVL_2 UINT32_C(0x2) - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_LEVEL_LAST HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_LEVEL_LVL_2 - /* Page size. */ - uint8_t page_size; - /* 4KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_4K UINT32_C(0x0) - /* 8KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_8K UINT32_C(0x1) - /* 64KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_64K UINT32_C(0x4) - /* 128KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_128K UINT32_C(0x5) - /* 256KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_256K UINT32_C(0x6) - /* 512KB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_512K UINT32_C(0x7) - /* 1MB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_1M UINT32_C(0x8) - /* 2MB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_2M UINT32_C(0x9) - /* 4MB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_4M UINT32_C(0xa) - /* 8MB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_8M UINT32_C(0xb) - /* 1GB page size. */ - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_1G UINT32_C(0x12) - #define HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_LAST HWRM_TF_CTXT_MEM_ALLOC_OUTPUT_PAGE_SIZE_1G - /* unused. */ - uint8_t unused0; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tf_ctxt_mem_alloc_output_t, *phwrm_tf_ctxt_mem_alloc_output_t; - -/************************* - * hwrm_tf_ctxt_mem_free * - *************************/ - - -/* hwrm_tf_ctxt_mem_free_input (size:320b/40B) */ - -typedef struct hwrm_tf_ctxt_mem_free_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; - /* Counter PBL indirect levels. */ - uint8_t page_level; - /* PBL pointer is physical start address. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_LEVEL_LVL_0 UINT32_C(0x0) - /* PBL pointer points to PTE table. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_LEVEL_LVL_1 UINT32_C(0x1) - /* - * PBL pointer points to PDE table with each entry pointing - * to PTE tables. - */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_LEVEL_LVL_2 UINT32_C(0x2) - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_LEVEL_LAST HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_LEVEL_LVL_2 - /* Page size. */ - uint8_t page_size; - /* 4KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_4K UINT32_C(0x0) - /* 8KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_8K UINT32_C(0x1) - /* 64KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_64K UINT32_C(0x4) - /* 128KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_128K UINT32_C(0x5) - /* 256KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_256K UINT32_C(0x6) - /* 512KB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_512K UINT32_C(0x7) - /* 1MB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_1M UINT32_C(0x8) - /* 2MB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_2M UINT32_C(0x9) - /* 4MB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_4M UINT32_C(0xa) - /* 8MB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_8M UINT32_C(0xb) - /* 1GB page size. */ - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_1G UINT32_C(0x12) - #define HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_LAST HWRM_TF_CTXT_MEM_FREE_INPUT_PAGE_SIZE_1G - /* unused. */ - uint8_t unused0[2]; - /* Pointer to the PBL, or PDL depending on number of levels */ - uint64_t page_dir; - /* Size of memory allocated. */ - uint32_t mem_size; - /* unused. */ - uint8_t unused1[4]; -} hwrm_tf_ctxt_mem_free_input_t, *phwrm_tf_ctxt_mem_free_input_t; - -/* hwrm_tf_ctxt_mem_free_output (size:128b/16B) */ - -typedef struct hwrm_tf_ctxt_mem_free_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* unused. */ - uint8_t unused0[7]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tf_ctxt_mem_free_output_t, *phwrm_tf_ctxt_mem_free_output_t; - -/************************* - * hwrm_tf_ctxt_mem_rgtr * - *************************/ - - -/* hwrm_tf_ctxt_mem_rgtr_input (size:256b/32B) */ - -typedef struct hwrm_tf_ctxt_mem_rgtr_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Control flags. */ - uint16_t flags; - /* Counter PBL indirect levels. */ - uint8_t page_level; - /* PBL pointer is physical start address. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_LEVEL_LVL_0 UINT32_C(0x0) - /* PBL pointer points to PTE table. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_LEVEL_LVL_1 UINT32_C(0x1) - /* - * PBL pointer points to PDE table with each entry pointing - * to PTE tables. - */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_LEVEL_LVL_2 UINT32_C(0x2) - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_LEVEL_LAST HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_LEVEL_LVL_2 - /* Page size. */ - uint8_t page_size; - /* 4KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_4K UINT32_C(0x0) - /* 8KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_8K UINT32_C(0x1) - /* 64KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_64K UINT32_C(0x4) - /* 128KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_128K UINT32_C(0x5) - /* 256KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_256K UINT32_C(0x6) - /* 512KB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_512K UINT32_C(0x7) - /* 1MB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_1M UINT32_C(0x8) - /* 2MB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_2M UINT32_C(0x9) - /* 4MB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_4M UINT32_C(0xa) - /* 8MB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_8M UINT32_C(0xb) - /* 1GB page size. */ - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_1G UINT32_C(0x12) - #define HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_LAST HWRM_TF_CTXT_MEM_RGTR_INPUT_PAGE_SIZE_1G - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; - /* Pointer to the PBL, or PDL depending on number of levels */ - uint64_t page_dir; -} hwrm_tf_ctxt_mem_rgtr_input_t, *phwrm_tf_ctxt_mem_rgtr_input_t; - -/* hwrm_tf_ctxt_mem_rgtr_output (size:128b/16B) */ - -typedef struct hwrm_tf_ctxt_mem_rgtr_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* - * Id/Handle to the recently register context memory. This - * handle is passed to the TF session. - */ - uint16_t ctx_id; - /* unused. */ - uint8_t unused0[5]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tf_ctxt_mem_rgtr_output_t, *phwrm_tf_ctxt_mem_rgtr_output_t; - -/*************************** - * hwrm_tf_ctxt_mem_unrgtr * - ***************************/ - - -/* hwrm_tf_ctxt_mem_unrgtr_input (size:192b/24B) */ - -typedef struct hwrm_tf_ctxt_mem_unrgtr_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* - * Id/Handle to the recently register context memory. This - * handle is passed to the TF session. - */ - uint16_t ctx_id; - /* unused. */ - uint8_t unused0[2]; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; -} hwrm_tf_ctxt_mem_unrgtr_input_t, *phwrm_tf_ctxt_mem_unrgtr_input_t; - -/* hwrm_tf_ctxt_mem_unrgtr_output (size:128b/16B) */ - -typedef struct hwrm_tf_ctxt_mem_unrgtr_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* unused. */ - uint8_t unused0[7]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tf_ctxt_mem_unrgtr_output_t, *phwrm_tf_ctxt_mem_unrgtr_output_t; +} hwrm_tf_tbl_type_get_output_t, *phwrm_tf_tbl_type_get_output_t; /************************ - * hwrm_tf_ext_em_qcaps * + * hwrm_tf_tbl_type_set * ************************/ -/* hwrm_tf_ext_em_qcaps_input (size:192b/24B) */ +/* hwrm_tf_tbl_type_set_input (size:1024b/128B) */ -typedef struct hwrm_tf_ext_em_qcaps_input { +typedef struct hwrm_tf_tbl_type_set_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -49810,221 +55019,50 @@ typedef struct hwrm_tf_ext_em_qcaps_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; - /* Control flags. */ - uint32_t flags; - /* Indicates the flow direction. */ - #define HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_LAST HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_TX - /* When set to 1, all offloaded flows will be sent to EXT EM. */ - #define HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_PREFERRED_OFFLOAD UINT32_C(0x2) /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ uint32_t fw_session_id; -} hwrm_tf_ext_em_qcaps_input_t, *phwrm_tf_ext_em_qcaps_input_t; - -/* hwrm_tf_ext_em_qcaps_output (size:384b/48B) */ - -typedef struct hwrm_tf_ext_em_qcaps_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - uint32_t flags; - /* - * When set to 1, indicates the FW supports the Centralized - * Memory Model. The concept designates one entity for the - * memory allocation while all others ‘subscribe’ to it. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_FLAGS_CENTRALIZED_MEMORY_MODEL_SUPPORTED UINT32_C(0x1) - /* - * When set to 1, indicates the FW supports the Detached - * Centralized Memory Model. The memory is allocated and managed - * as a separate entity. All PFs and VFs will be granted direct - * or semi-direct access to the allocated memory while none of - * which can interfere with the management of the memory. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_FLAGS_DETACHED_CENTRALIZED_MEMORY_MODEL_SUPPORTED UINT32_C(0x2) - /* When set to 1, indicates FW support for host based EEM memory. */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_FLAGS_HOST_MEMORY_SUPPORTED UINT32_C(0x4) - /* When set to 1, indicates FW support for on-chip based EEM memory. */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_FLAGS_FW_MEMORY_SUPPORTED UINT32_C(0x8) - /* unused. */ - uint32_t unused0; - /* Support flags. */ - uint32_t supported; - /* - * If set to 1, then EXT EM KEY0 table is supported using - * crc32 hash. - * If set to 0, EXT EM KEY0 table is not supported. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_KEY0_TABLE UINT32_C(0x1) - /* - * If set to 1, then EXT EM KEY1 table is supported using - * lookup3 hash. - * If set to 0, EXT EM KEY1 table is not supported. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_KEY1_TABLE UINT32_C(0x2) - /* - * If set to 1, then EXT EM External Record table is supported. - * If set to 0, EXT EM External Record table is not - * supported. (This table includes action record, EFC - * pointers, encap pointers) - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_EXTERNAL_RECORD_TABLE UINT32_C(0x4) - /* - * If set to 1, then EXT EM External Flow Counters table is - * supported. - * If set to 0, EXT EM External Flow Counters table is not - * supported. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_EXTERNAL_FLOW_COUNTERS_TABLE UINT32_C(0x8) - /* - * If set to 1, then FID table used for implicit flow flush - * is supported. - * If set to 0, then FID table used for implicit flow flush - * is not supported. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_FID_TABLE UINT32_C(0x10) - /* - * If set to 1, then table scopes are supported. - * If set to 0, then table scopes are not supported. - */ - #define HWRM_TF_EXT_EM_QCAPS_OUTPUT_SUPPORTED_TBL_SCOPES UINT32_C(0x20) - /* - * The maximum number of entries supported by EXT EM. When - * configuring the host memory the number of numbers of - * entries that can supported are - - * 32k, 64k 128k, 256k, 512k, 1M, 2M, 4M, 8M, 32M, 64M, - * 128M entries. - * Any value that are not these values, the FW will round - * down to the closest support number of entries. - */ - uint32_t max_entries_supported; - /* - * The entry size in bytes of each entry in the EXT EM - * KEY0/KEY1 tables. - */ - uint16_t key_entry_size; - /* - * The entry size in bytes of each entry in the EXT EM RECORD - * tables. - */ - uint16_t record_entry_size; - /* The entry size in bytes of each entry in the EXT EM EFC tables. */ - uint16_t efc_entry_size; - /* The FID size in bytes of each entry in the EXT EM FID tables. */ - uint16_t fid_entry_size; - /* Maximum number of ctxt mem allocations allowed. */ - uint32_t max_ctxt_mem_allocs; - /* - * Maximum number of static buckets that can be assigned to lookup - * table scopes. - */ - uint32_t max_static_buckets; - /* unused. */ - uint8_t unused1[7]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tf_ext_em_qcaps_output_t, *phwrm_tf_ext_em_qcaps_output_t; - -/********************* - * hwrm_tf_ext_em_op * - *********************/ - - -/* hwrm_tf_ext_em_op_input (size:256b/32B) */ - -typedef struct hwrm_tf_ext_em_op_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; /* Control flags. */ uint16_t flags; /* Indicates the flow direction. */ - #define HWRM_TF_EXT_EM_OP_INPUT_FLAGS_DIR UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR UINT32_C(0x1) /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_EXT_EM_OP_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_EXT_EM_OP_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_EXT_EM_OP_INPUT_FLAGS_DIR_LAST HWRM_TF_EXT_EM_OP_INPUT_FLAGS_DIR_TX + #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DIR_TX + /* Indicate table data is being sent via DMA. */ + #define HWRM_TF_TBL_TYPE_SET_INPUT_FLAGS_DMA UINT32_C(0x2) + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_LAST HWRM_TF_TBL_TYPE_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE /* unused. */ - uint16_t unused0; - /* The number of EXT EM key table entries to be configured. */ - uint16_t op; - /* This value is reserved and should not be used. */ - #define HWRM_TF_EXT_EM_OP_INPUT_OP_RESERVED UINT32_C(0x0) - /* - * To properly stop EXT EM and ensure there are no DMA's, - * the caller must disable EXT EM for the given PF, using - * this call. This will safely disable EXT EM and ensure - * that all DMA'ed to the keys/records/efc have been - * completed. - */ - #define HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE UINT32_C(0x1) - /* - * Once the EXT EM host memory has been configured, EXT EM - * options have been configured. Then the caller should - * enable EXT EM for the given PF. Note once this call has - * been made, then the EXT EM mechanism will be active and - * DMA's will occur as packets are processed. - */ - #define HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_ENABLE UINT32_C(0x2) + uint8_t unused0; /* - * Clear EXT EM settings for the given PF so that the - * register values are reset back to their initial state. + * Type of the resource, defined globally in the + * hwrm_tf_resc_type enum. */ - #define HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_CLEANUP UINT32_C(0x3) - #define HWRM_TF_EXT_EM_OP_INPUT_OP_LAST HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_CLEANUP - /* unused. */ - uint16_t unused1; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; - /* unused. */ - uint32_t unused2; -} hwrm_tf_ext_em_op_input_t, *phwrm_tf_ext_em_op_input_t; + uint32_t type; + /* Index of the type to retrieve. */ + uint32_t index; + /* Size of the data to set. */ + uint16_t size; + /* unused */ + uint8_t unused1[6]; + /* Data to be set. */ + uint8_t data[88]; +} hwrm_tf_tbl_type_set_input_t, *phwrm_tf_tbl_type_set_input_t; -/* hwrm_tf_ext_em_op_output (size:128b/16B) */ +/* hwrm_tf_tbl_type_set_output (size:128b/16B) */ -typedef struct hwrm_tf_ext_em_op_output { +typedef struct hwrm_tf_tbl_type_set_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -50036,24 +55074,24 @@ typedef struct hwrm_tf_ext_em_op_output { /* unused. */ uint8_t unused0[7]; /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. */ uint8_t valid; -} hwrm_tf_ext_em_op_output_t, *phwrm_tf_ext_em_op_output_t; +} hwrm_tf_tbl_type_set_output_t, *phwrm_tf_tbl_type_set_output_t; -/********************** - * hwrm_tf_ext_em_cfg * - **********************/ +/************************* + * hwrm_tf_tbl_type_free * + *************************/ -/* hwrm_tf_ext_em_cfg_input (size:512b/64B) */ +/* hwrm_tf_tbl_type_free_input (size:256b/32B) */ -typedef struct hwrm_tf_ext_em_cfg_input { +typedef struct hwrm_tf_tbl_type_free_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -50082,212 +55120,42 @@ typedef struct hwrm_tf_ext_em_cfg_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ + uint32_t fw_session_id; /* Control flags. */ - uint32_t flags; + uint16_t flags; /* Indicates the flow direction. */ - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_FREE_INPUT_FLAGS_DIR UINT32_C(0x1) /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + #define HWRM_TF_TBL_TYPE_FREE_INPUT_FLAGS_DIR_RX UINT32_C(0x0) /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_LAST HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_TX - /* When set to 1, all offloaded flows will be sent to EXT EM. */ - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_PREFERRED_OFFLOAD UINT32_C(0x2) - /* When set to 1, secondary, 0 means primary. */ - #define HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_SECONDARY_PF UINT32_C(0x4) - /* - * Group_id which used by Firmware to identify memory pools belonging - * to certain group. - */ - uint16_t group_id; - /* - * Dynamically reconfigure EEM pending cache every 1/10th of second. - * If set to 0 it will disable the EEM HW flush of the pending cache. - */ - uint8_t flush_interval; - /* unused. */ + #define HWRM_TF_TBL_TYPE_FREE_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_TBL_TYPE_FREE_INPUT_FLAGS_DIR_LAST HWRM_TF_TBL_TYPE_FREE_INPUT_FLAGS_DIR_TX + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_LAST HWRM_TF_TBL_TYPE_FREE_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE + /* Unused */ uint8_t unused0; /* - * Configured EXT EM with the given number of entries. All - * the EXT EM tables KEY0, KEY1, RECORD, EFC all have the - * same number of entries and all tables will be configured - * using this value. Current minimum value is 32k. Current - * maximum value is 128M. - */ - uint32_t num_entries; - uint32_t enables; - /* - * This bit must be '1' for the group_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_GROUP_ID UINT32_C(0x1) - /* - * This bit must be '1' for the flush_interval field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_FLUSH_INTERVAL UINT32_C(0x2) - /* - * This bit must be '1' for the num_entries field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_NUM_ENTRIES UINT32_C(0x4) - /* - * This bit must be '1' for the key0_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_KEY0_CTX_ID UINT32_C(0x8) - /* - * This bit must be '1' for the key1_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_KEY1_CTX_ID UINT32_C(0x10) - /* - * This bit must be '1' for the record_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_RECORD_CTX_ID UINT32_C(0x20) - /* - * This bit must be '1' for the efc_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_EFC_CTX_ID UINT32_C(0x40) - /* - * This bit must be '1' for the fid_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_FID_CTX_ID UINT32_C(0x80) - /* - * This bit must be '1' for the action_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_ACTION_CTX_ID UINT32_C(0x100) - /* - * This bit must be '1' for the action_tbl_scope field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_ACTION_TBL_SCOPE UINT32_C(0x200) - /* - * This bit must be '1' for the lkup_ctx_id field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_LKUP_CTX_ID UINT32_C(0x400) - /* - * This bit must be '1' for the lkup_tbl_scope field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_LKUP_TBL_SCOPE UINT32_C(0x800) - /* - * This bit must be '1' for the lkup_static_buckets field to be - * configured. - */ - #define HWRM_TF_EXT_EM_CFG_INPUT_ENABLES_LKUP_STATIC_BUCKETS UINT32_C(0x1000) - /* Configured EXT EM with the given context if for KEY0 table. */ - uint16_t key0_ctx_id; - /* Configured EXT EM with the given context if for KEY1 table. */ - uint16_t key1_ctx_id; - /* Configured EXT EM with the given context if for RECORD table. */ - uint16_t record_ctx_id; - /* Configured EXT EM with the given context if for EFC table. */ - uint16_t efc_ctx_id; - /* Configured EXT EM with the given context if for EFC table. */ - uint16_t fid_ctx_id; - /* Context id of action table scope. */ - uint16_t action_ctx_id; - /* Table scope id used for action record entries. */ - uint16_t action_tbl_scope; - /* Context id of lookup table scope. */ - uint16_t lkup_ctx_id; - /* Table scope id used for EM lookup entries. */ - uint16_t lkup_tbl_scope; - /* unused. */ - uint16_t unused1; - /* - * Number of 32B static buckets to be allocated at the beginning - * of table scope. - */ - uint32_t lkup_static_buckets; - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; - /* unused. */ - uint32_t unused2; -} hwrm_tf_ext_em_cfg_input_t, *phwrm_tf_ext_em_cfg_input_t; - -/* hwrm_tf_ext_em_cfg_output (size:128b/16B) */ - -typedef struct hwrm_tf_ext_em_cfg_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* unused. */ - uint8_t unused0[7]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. + * Table entry to be freed by the firmware using the parameters + * above. */ - uint8_t valid; -} hwrm_tf_ext_em_cfg_output_t, *phwrm_tf_ext_em_cfg_output_t; - -/*********************** - * hwrm_tf_ext_em_qcfg * - ***********************/ - - -/* hwrm_tf_ext_em_qcfg_input (size:192b/24B) */ - -typedef struct hwrm_tf_ext_em_qcfg_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Control flags. */ - uint32_t flags; - /* Indicates the flow direction. */ - #define HWRM_TF_EXT_EM_QCFG_INPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_EXT_EM_QCFG_INPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_EXT_EM_QCFG_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_EXT_EM_QCFG_INPUT_FLAGS_DIR_LAST HWRM_TF_EXT_EM_QCFG_INPUT_FLAGS_DIR_TX - /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ - uint32_t fw_session_id; -} hwrm_tf_ext_em_qcfg_input_t, *phwrm_tf_ext_em_qcfg_input_t; + uint16_t idx_tbl_id; + /* Unused */ + uint8_t unused1[6]; +} hwrm_tf_tbl_type_free_input_t, *phwrm_tf_tbl_type_free_input_t; -/* hwrm_tf_ext_em_qcfg_output (size:448b/56B) */ +/* hwrm_tf_tbl_type_free_output (size:128b/16B) */ -typedef struct hwrm_tf_ext_em_qcfg_output { +typedef struct hwrm_tf_tbl_type_free_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -50296,92 +55164,20 @@ typedef struct hwrm_tf_ext_em_qcfg_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Control flags. */ - uint32_t flags; - /* Indicates the flow direction. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_DIR_LAST HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_DIR_TX - /* When set to 1, all offloaded flows will be sent to EXT EM. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_FLAGS_PREFERRED_OFFLOAD UINT32_C(0x2) - /* The number of entries the FW has configured for EXT EM. */ - uint32_t num_entries; - /* Configured EXT EM with the given context if for KEY0 table. */ - uint16_t key0_ctx_id; - /* Configured EXT EM with the given context if for KEY1 table. */ - uint16_t key1_ctx_id; - /* Configured EXT EM with the given context if for RECORD table. */ - uint16_t record_ctx_id; - /* Configured EXT EM with the given context if for EFC table. */ - uint16_t efc_ctx_id; - /* Configured EXT EM with the given context if for EFC table. */ - uint16_t fid_ctx_id; - /* unused. */ - uint16_t unused0; - uint32_t supported; - /* This bit must be '1' for the group_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_GROUP_ID UINT32_C(0x1) - /* This bit must be '1' for the flush_interval field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_FLUSH_INTERVAL UINT32_C(0x2) - /* This bit must be '1' for the num_entries field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_NUM_ENTRIES UINT32_C(0x4) - /* This bit must be '1' for the key0_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_KEY0_CTX_ID UINT32_C(0x8) - /* This bit must be '1' for the key1_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_KEY1_CTX_ID UINT32_C(0x10) - /* This bit must be '1' for the record_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_RECORD_CTX_ID UINT32_C(0x20) - /* This bit must be '1' for the efc_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_EFC_CTX_ID UINT32_C(0x40) - /* This bit must be '1' for the fid_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_FID_CTX_ID UINT32_C(0x80) - /* This bit must be '1' for the action_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_ACTION_CTX_ID UINT32_C(0x100) - /* This bit must be '1' for the action_tbl_scope field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_ACTION_TBL_SCOPE UINT32_C(0x200) - /* This bit must be '1' for the lkup_ctx_id field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_LKUP_CTX_ID UINT32_C(0x400) - /* This bit must be '1' for the lkup_tbl_scope field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_LKUP_TBL_SCOPE UINT32_C(0x800) - /* This bit must be '1' for the lkup_static_buckets field is set. */ - #define HWRM_TF_EXT_EM_QCFG_OUTPUT_SUPPORTED_LKUP_STATIC_BUCKETS UINT32_C(0x1000) - /* - * Group id is used by firmware to identify memory pools belonging - * to certain group. - */ - uint16_t group_id; - /* EEM pending cache flush interval in 1/10th of second. */ - uint8_t flush_interval; - /* unused. */ - uint8_t unused1; - /* Context id of action table scope. */ - uint16_t action_ctx_id; - /* Table scope id used for action record entries. */ - uint16_t action_tbl_scope; - /* Context id of lookup table scope. */ - uint16_t lkup_ctx_id; - /* Table scope id used for EM lookup entries. */ - uint16_t lkup_tbl_scope; - /* - * Number of 32B static buckets to be allocated at the beginning - * of table scope. - */ - uint32_t lkup_static_buckets; - /* unused. */ - uint8_t unused2[7]; + /* Response code. */ + uint32_t resp_code; + /* unused */ + uint8_t unused0[3]; /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. */ uint8_t valid; -} hwrm_tf_ext_em_qcfg_output_t, *phwrm_tf_ext_em_qcfg_output_t; +} hwrm_tf_tbl_type_free_output_t, *phwrm_tf_tbl_type_free_output_t; /********************* * hwrm_tf_em_insert * @@ -50462,7 +55258,16 @@ typedef struct hwrm_tf_em_insert_output { /* Number of word entries consumed by the key. */ uint8_t num_of_entries; /* unused. */ - uint32_t unused0; + uint8_t unused0[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; } hwrm_tf_em_insert_output_t, *phwrm_tf_em_insert_output_t; /************************** @@ -50512,6 +55317,8 @@ typedef struct hwrm_tf_em_hash_insert_input { /* If this bit is set to 1, then it indicates tx flow. */ #define HWRM_TF_EM_HASH_INSERT_INPUT_FLAGS_DIR_TX UINT32_C(0x1) #define HWRM_TF_EM_HASH_INSERT_INPUT_FLAGS_DIR_LAST HWRM_TF_EM_HASH_INSERT_INPUT_FLAGS_DIR_TX + /* Indicates table data is being sent via DMA. */ + #define HWRM_TF_EM_HASH_INSERT_INPUT_FLAGS_DMA UINT32_C(0x2) /* Number of bits in the EM record. */ uint16_t em_record_size_bits; /* CRC32 hash of key. */ @@ -50544,7 +55351,16 @@ typedef struct hwrm_tf_em_hash_insert_output { /* Number of word entries consumed by the key. */ uint8_t num_of_entries; /* unused. */ - uint32_t unused0; + uint8_t unused0[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; } hwrm_tf_em_hash_insert_output_t, *phwrm_tf_em_hash_insert_output_t; /********************* @@ -50620,7 +55436,16 @@ typedef struct hwrm_tf_em_delete_output { /* Original stack allocation index. */ uint16_t em_index; /* unused. */ - uint16_t unused0[3]; + uint8_t unused0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; } hwrm_tf_em_delete_output_t, *phwrm_tf_em_delete_output_t; /******************* @@ -50694,7 +55519,16 @@ typedef struct hwrm_tf_em_move_output { /* Index of old entry. */ uint16_t em_index; /* unused. */ - uint16_t unused0[3]; + uint8_t unused0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; } hwrm_tf_em_move_output_t, *phwrm_tf_em_move_output_t; /******************** @@ -50793,7 +55627,7 @@ typedef struct hwrm_tf_tcam_set_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -50890,7 +55724,7 @@ typedef struct hwrm_tf_tcam_get_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -50974,7 +55808,7 @@ typedef struct hwrm_tf_tcam_move_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -51058,7 +55892,7 @@ typedef struct hwrm_tf_tcam_free_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -51112,6 +55946,8 @@ typedef struct hwrm_tf_global_cfg_set_input { /* If this bit is set to 1, then it indicates tx flow. */ #define HWRM_TF_GLOBAL_CFG_SET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) #define HWRM_TF_GLOBAL_CFG_SET_INPUT_FLAGS_DIR_LAST HWRM_TF_GLOBAL_CFG_SET_INPUT_FLAGS_DIR_TX + /* Indicate device data is being sent via DMA. */ + #define HWRM_TF_GLOBAL_CFG_SET_INPUT_FLAGS_DMA UINT32_C(0x2) /* Global Cfg type */ uint32_t type; /* Offset of the type */ @@ -51143,7 +55979,7 @@ typedef struct hwrm_tf_global_cfg_set_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -51207,7 +56043,7 @@ typedef struct hwrm_tf_global_cfg_get_input { uint8_t unused0[6]; } hwrm_tf_global_cfg_get_input_t, *phwrm_tf_global_cfg_get_input_t; -/* hwrm_tf_global_cfg_get_output (size:256b/32B) */ +/* hwrm_tf_global_cfg_get_output (size:2240b/280B) */ typedef struct hwrm_tf_global_cfg_get_output { /* The specific error status for the command. */ @@ -51223,7 +56059,18 @@ typedef struct hwrm_tf_global_cfg_get_output { /* unused. */ uint8_t unused0[6]; /* Data to set */ - uint8_t data[16]; + uint8_t data[256]; + /* unused. */ + uint8_t unused1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field is + * written last. + */ + uint8_t valid; } hwrm_tf_global_cfg_get_output_t, *phwrm_tf_global_cfg_get_output_t; /********************** @@ -51655,6 +56502,208 @@ typedef struct hwrm_tf_session_hotup_state_get_output { uint8_t valid; } hwrm_tf_session_hotup_state_get_output_t, *phwrm_tf_session_hotup_state_get_output_t; +/************************** + * hwrm_tf_resc_usage_set * + **************************/ + + +/* hwrm_tf_resc_usage_set_input (size:1024b/128B) */ + +typedef struct hwrm_tf_resc_usage_set_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ + uint32_t fw_session_id; + /* Control flags. */ + uint16_t flags; + /* Indicates the flow direction. */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DIR_LAST HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DIR_TX + /* Indicate table data is being sent via DMA. */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_FLAGS_DMA UINT32_C(0x2) + /* Types of the resource to set their usage state. */ + uint16_t types; + /* WC TCAM Pool */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_WC_TCAM UINT32_C(0x1) + /* EM Internal Memory Pool */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_EM UINT32_C(0x2) + /* Meter Instance */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_METER UINT32_C(0x4) + /* Counter Record Table */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_COUNTER UINT32_C(0x8) + /* Action Record Table */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_ACTION UINT32_C(0x10) + /* ACT MODIFY/ENCAP Record Table */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_ACT_MOD_ENCAP UINT32_C(0x20) + /* Source Property SMAC Record Table */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_SP_SMAC UINT32_C(0x40) + /* All Resource Types */ + #define HWRM_TF_RESC_USAGE_SET_INPUT_TYPES_ALL UINT32_C(0x80) + /* Size of the data to set. */ + uint16_t size; + /* unused */ + uint8_t unused1[6]; + /* Data to be set. */ + uint8_t data[96]; +} hwrm_tf_resc_usage_set_input_t, *phwrm_tf_resc_usage_set_input_t; + +/* hwrm_tf_resc_usage_set_output (size:128b/16B) */ + +typedef struct hwrm_tf_resc_usage_set_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* unused. */ + uint8_t unused0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tf_resc_usage_set_output_t, *phwrm_tf_resc_usage_set_output_t; + +/**************************** + * hwrm_tf_resc_usage_query * + ****************************/ + + +/* hwrm_tf_resc_usage_query_input (size:256b/32B) */ + +typedef struct hwrm_tf_resc_usage_query_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ + uint32_t fw_session_id; + /* Control flags. */ + uint16_t flags; + /* Indicates the flow direction. */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_LAST HWRM_TF_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_TX + /* unused. */ + uint8_t unused0[2]; + /* Types of the resource to retrieve their usage state. */ + uint16_t types; + /* WC TCAM Pool */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_WC_TCAM UINT32_C(0x1) + /* EM Internal Memory Pool */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_EM UINT32_C(0x2) + /* Meter Instance */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_METER UINT32_C(0x4) + /* Counter Record Table */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_COUNTER UINT32_C(0x8) + /* Action Record Table */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_ACTION UINT32_C(0x10) + /* ACT MODIFY/ENCAP Record Table */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_ACT_MOD_ENCAP UINT32_C(0x20) + /* Source Property SMAC Record Table */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_SP_SMAC UINT32_C(0x40) + /* All Resource Types */ + #define HWRM_TF_RESC_USAGE_QUERY_INPUT_TYPES_ALL UINT32_C(0x80) + /* unused */ + uint8_t unused1[6]; +} hwrm_tf_resc_usage_query_input_t, *phwrm_tf_resc_usage_query_input_t; + +/* hwrm_tf_resc_usage_query_output (size:960b/120B) */ + +typedef struct hwrm_tf_resc_usage_query_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Response code. */ + uint32_t resp_code; + /* Response size. */ + uint16_t size; + /* unused */ + uint16_t unused0; + /* Response data. */ + uint8_t data[96]; + /* unused */ + uint8_t unused1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tf_resc_usage_query_output_t, *phwrm_tf_resc_usage_query_output_t; + /**************************** * hwrm_tfc_tbl_scope_qcaps * ****************************/ @@ -51722,7 +56771,7 @@ typedef struct hwrm_tfc_tbl_scope_qcaps_output { uint8_t tbl_scope_capable; /* * log2 of the number of lookup static buckets that a table scope can - * support. This field is only valid if tbl_scope_capable is not zero. + * support. This field is only valid if tbl_scope_capable is not zero. */ uint8_t max_lkup_static_buckets_exp; /* unused. */ @@ -51752,7 +56801,7 @@ typedef struct hwrm_tfc_tbl_scope_qcaps_output { * a fid_cnt of 0 that also means that the table scope ID has * been freed. */ -/* hwrm_tfc_tbl_scope_id_alloc_input (size:192b/24B) */ +/* hwrm_tfc_tbl_scope_id_alloc_input (size:256b/32B) */ typedef struct hwrm_tfc_tbl_scope_id_alloc_input { /* The HWRM command request type. */ @@ -51783,26 +56832,37 @@ typedef struct hwrm_tfc_tbl_scope_id_alloc_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; /* The maximum number of pools for this table scope. */ uint16_t max_pools; /* Non-zero if this table scope is shared. */ uint8_t shared; /* * The size of the lookup pools per direction expressed as - * log2(max_records/max_pools). That is, size=2^exp. + * log2(max_records/max_pools). That is, size=2^exp. * * Array is indexed by enum cfa_dir. */ uint8_t lkup_pool_sz_exp[2]; /* * The size of the action pools per direction expressed as - * log2(max_records/max_pools). That is, size=2^exp. + * log2(max_records/max_pools). That is, size=2^exp. * * Array is indexed by enum cfa_dir. */ uint8_t act_pool_sz_exp[2]; + /* Application type. 0 (AFM), 1 (TF) */ + uint8_t app_type; /* unused. */ - uint8_t unused0; + uint8_t unused0[6]; } hwrm_tfc_tbl_scope_id_alloc_input_t, *phwrm_tfc_tbl_scope_id_alloc_input_t; /* hwrm_tfc_tbl_scope_id_alloc_output (size:128b/16B) */ @@ -51886,7 +56946,7 @@ typedef struct hwrm_tfc_tbl_scope_config_input { /* * The number of minimum sized lkup records per direction. * In this usage, records are the minimum lookup memory - * allocation unit in a table scope. This value is the total + * allocation unit in a table scope. This value is the total * memory required for buckets and entries. * * Array is indexed by enum cfa_dir. @@ -52051,10 +57111,19 @@ typedef struct hwrm_tfc_tbl_scope_fid_add_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; /* The table scope ID. */ uint8_t tsid; /* unused. */ - uint8_t unused0[7]; + uint8_t unused0[5]; } hwrm_tfc_tbl_scope_fid_add_input_t, *phwrm_tfc_tbl_scope_fid_add_input_t; /* hwrm_tfc_tbl_scope_fid_add_output (size:128b/16B) */ @@ -52120,10 +57189,19 @@ typedef struct hwrm_tfc_tbl_scope_fid_rem_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; /* The table scope ID. */ uint8_t tsid; /* unused. */ - uint8_t unused0[7]; + uint8_t unused0[5]; } hwrm_tfc_tbl_scope_fid_rem_input_t, *phwrm_tfc_tbl_scope_fid_rem_input_t; /* hwrm_tfc_tbl_scope_fid_rem_output (size:128b/16B) */ @@ -52152,176 +57230,6 @@ typedef struct hwrm_tfc_tbl_scope_fid_rem_output { uint8_t valid; } hwrm_tfc_tbl_scope_fid_rem_output_t, *phwrm_tfc_tbl_scope_fid_rem_output_t; -/********************************* - * hwrm_tfc_tbl_scope_pool_alloc * - *********************************/ - - -/* hwrm_tfc_tbl_scope_pool_alloc_input (size:192b/24B) */ - -typedef struct hwrm_tfc_tbl_scope_pool_alloc_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Table Scope ID */ - uint8_t tsid; - /* Control flags. Direction and type. */ - uint8_t flags; - /* Indicates the flow direction. */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_DIR_LAST HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_DIR_TX - /* Indicates the table type. */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_TYPE UINT32_C(0x2) - /* Lookup table */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_TYPE_LOOKUP (UINT32_C(0x0) << 1) - /* Action table */ - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_TYPE_ACTION (UINT32_C(0x1) << 1) - #define HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_TYPE_LAST HWRM_TFC_TBL_SCOPE_POOL_ALLOC_INPUT_FLAGS_TYPE_ACTION - /* Unused */ - uint8_t unused[6]; -} hwrm_tfc_tbl_scope_pool_alloc_input_t, *phwrm_tfc_tbl_scope_pool_alloc_input_t; - -/* hwrm_tfc_tbl_scope_pool_alloc_output (size:128b/16B) */ - -typedef struct hwrm_tfc_tbl_scope_pool_alloc_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* Pool ID */ - uint16_t pool_id; - /* Pool size exponent. An exponent of 0 indicates a failure. */ - uint8_t pool_sz_exp; - /* unused. */ - uint8_t unused1[4]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tfc_tbl_scope_pool_alloc_output_t, *phwrm_tfc_tbl_scope_pool_alloc_output_t; - -/******************************** - * hwrm_tfc_tbl_scope_pool_free * - ********************************/ - - -/* hwrm_tfc_tbl_scope_pool_free_input (size:192b/24B) */ - -typedef struct hwrm_tfc_tbl_scope_pool_free_input { - /* The HWRM command request type. */ - uint16_t req_type; - /* - * The completion ring to send the completion event on. This should - * be the NQ ID returned from the `nq_alloc` HWRM command. - */ - uint16_t cmpl_ring; - /* - * The sequence ID is used by the driver for tracking multiple - * commands. This ID is treated as opaque data by the firmware and - * the value is returned in the `hwrm_resp_hdr` upon completion. - */ - uint16_t seq_id; - /* - * The target ID of the command: - * * 0x0-0xFFF8 - The function ID - * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors - * * 0xFFFD - Reserved for user-space HWRM interface - * * 0xFFFF - HWRM - */ - uint16_t target_id; - /* - * A physical address pointer pointing to a host buffer that the - * command's response data will be written. This can be either a host - * physical address (HPA) or a guest physical address (GPA) and must - * point to a physically contiguous block of memory. - */ - uint64_t resp_addr; - /* Table Scope ID */ - uint8_t tsid; - /* Control flags. Direction and type. */ - uint8_t flags; - /* Indicates the flow direction. */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_DIR UINT32_C(0x1) - /* If this bit set to 0, then it indicates rx flow. */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_DIR_RX UINT32_C(0x0) - /* If this bit is set to 1, then it indicates tx flow. */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_DIR_TX UINT32_C(0x1) - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_DIR_LAST HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_DIR_TX - /* Indicates the table type. */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_TYPE UINT32_C(0x2) - /* Lookup table */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_TYPE_LOOKUP (UINT32_C(0x0) << 1) - /* Action table */ - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_TYPE_ACTION (UINT32_C(0x1) << 1) - #define HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_TYPE_LAST HWRM_TFC_TBL_SCOPE_POOL_FREE_INPUT_FLAGS_TYPE_ACTION - /* Pool ID */ - uint16_t pool_id; - /* Unused */ - uint8_t unused[4]; -} hwrm_tfc_tbl_scope_pool_free_input_t, *phwrm_tfc_tbl_scope_pool_free_input_t; - -/* hwrm_tfc_tbl_scope_pool_free_output (size:128b/16B) */ - -typedef struct hwrm_tfc_tbl_scope_pool_free_output { - /* The specific error status for the command. */ - uint16_t error_code; - /* The HWRM command request type. */ - uint16_t req_type; - /* The sequence ID from the original command. */ - uint16_t seq_id; - /* The length of the response data in number of bytes. */ - uint16_t resp_len; - /* unused. */ - uint8_t unused1[7]; - /* - * This field is used in Output records to indicate that the - * output is completely written to RAM. This field should be - * read as '1' to indicate that the output has been - * completely written. When writing a command completion or - * response to an internal processor, the order of writes has - * to be such that this field is written last. - */ - uint8_t valid; -} hwrm_tfc_tbl_scope_pool_free_output_t, *phwrm_tfc_tbl_scope_pool_free_output_t; - /***************************** * hwrm_tfc_session_id_alloc * *****************************/ @@ -52330,11 +57238,11 @@ typedef struct hwrm_tfc_tbl_scope_pool_free_output { /* * Allocate a TFC session. Requests the firmware to allocate a TFC * session identifier and associate a forwarding function with the - * session. Though there's not an explicit matching free for a session + * session. Though there's not an explicit matching free for a session * id alloc, dis-associating the last fid from a session id (fid_cnt goes * to 0), will result in this session id being freed automatically. */ -/* hwrm_tfc_session_id_alloc_input (size:128b/16B) */ +/* hwrm_tfc_session_id_alloc_input (size:192b/24B) */ typedef struct hwrm_tfc_session_id_alloc_input { /* The HWRM command request type. */ @@ -52365,6 +57273,17 @@ typedef struct hwrm_tfc_session_id_alloc_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* Unused field */ + uint8_t unused0[6]; } hwrm_tfc_session_id_alloc_input_t, *phwrm_tfc_session_id_alloc_input_t; /* hwrm_tfc_session_id_alloc_output (size:128b/16B) */ @@ -52437,12 +57356,21 @@ typedef struct hwrm_tfc_session_fid_add_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session identifier for the session created by the * firmware. */ uint16_t sid; /* Unused field */ - uint8_t unused0[6]; + uint8_t unused0[4]; } hwrm_tfc_session_fid_add_input_t, *phwrm_tfc_session_fid_add_input_t; /* hwrm_tfc_session_fid_add_output (size:128b/16B) */ @@ -52515,12 +57443,21 @@ typedef struct hwrm_tfc_session_fid_rem_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session identifier for the session created by the * firmware. */ uint16_t sid; /* Unused field */ - uint8_t unused0[6]; + uint8_t unused0[4]; } hwrm_tfc_session_fid_rem_input_t, *phwrm_tfc_session_fid_rem_input_t; /* hwrm_tfc_session_fid_rem_output (size:128b/16B) */ @@ -52593,6 +57530,15 @@ typedef struct hwrm_tfc_ident_alloc_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session identifier for the session created by the * firmware. Will be used to track this identifier. */ @@ -52621,7 +57567,7 @@ typedef struct hwrm_tfc_ident_alloc_input { #define HWRM_TFC_IDENT_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) #define HWRM_TFC_IDENT_ALLOC_INPUT_TRACK_TYPE_LAST HWRM_TFC_IDENT_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID /* Unused field */ - uint8_t unused0[3]; + uint8_t unused0; } hwrm_tfc_ident_alloc_input_t, *phwrm_tfc_ident_alloc_input_t; /* hwrm_tfc_ident_alloc_output (size:128b/16B) */ @@ -52696,6 +57642,15 @@ typedef struct hwrm_tfc_ident_free_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session identifier for the session created by the * firmware. Will be used to validate this request. */ @@ -52716,8 +57671,6 @@ typedef struct hwrm_tfc_ident_free_input { #define HWRM_TFC_IDENT_FREE_INPUT_FLAGS_DIR_LAST HWRM_TFC_IDENT_FREE_INPUT_FLAGS_DIR_TX /* The resource identifier to be freed */ uint16_t ident_id; - /* Reserved */ - uint8_t unused0[2]; } hwrm_tfc_ident_free_input_t, *phwrm_tfc_ident_free_input_t; /* hwrm_tfc_ident_free_output (size:128b/16B) */ @@ -52781,6 +57734,15 @@ typedef struct hwrm_tfc_idx_tbl_alloc_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session id for the session created by the * firmware. Will be used to track this index table entry * only if track type is track_type_sid. @@ -52796,8 +57758,13 @@ typedef struct hwrm_tfc_idx_tbl_alloc_input { #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_FLAGS_DIR_TX UINT32_C(0x1) #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_FLAGS_DIR_LAST HWRM_TFC_IDX_TBL_ALLOC_INPUT_FLAGS_DIR_TX /* - * CFA resource subtype. For definitions, please see - * cfa_v3/include/cfa_resources.h. + * This field is blktype specific. + * For blktype CFA - CFA resource subtype. For definitions, + * please see cfa_v3/include/cfa_resources.h. + * For blktype rxp, re_gparse, te_gparse - + * Tunnel Type. A value of zero (or unknown) means alloc. A known + * value (previously allocated dynamic UPAR for tunnel_type) means + * realloc. Will fail if a realloc is for previously allocated FID, */ uint8_t subtype; /* Describes the type of tracking id to be used */ @@ -52809,8 +57776,17 @@ typedef struct hwrm_tfc_idx_tbl_alloc_input { /* Tracked by function id */ #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_TRACK_TYPE_LAST HWRM_TFC_IDX_TBL_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID - /* Reserved */ - uint8_t unused0[3]; + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_LAST HWRM_TFC_IDX_TBL_ALLOC_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE } hwrm_tfc_idx_tbl_alloc_input_t, *phwrm_tfc_idx_tbl_alloc_input_t; /* hwrm_tfc_idx_tbl_alloc_output (size:128b/16B) */ @@ -52879,6 +57855,15 @@ typedef struct hwrm_tfc_idx_tbl_alloc_set_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session id for the session created by the * firmware. Will be used to track this index table entry * only if track type is track_type_sid. @@ -52899,8 +57884,13 @@ typedef struct hwrm_tfc_idx_tbl_alloc_set_input { */ #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_FLAGS_DMA UINT32_C(0x2) /* - * CFA resource subtype. For definitions, please see - * cfa_v3/include/cfa_resources.h. + * This field is blktype specific. + * For blktype CFA - CFA resource subtype. For definitions, + * please see cfa_v3/include/cfa_resources.h. + * For blktype rxp, re_gparse, te_gparse - + * Tunnel Type. A value of zero (or unknown) means alloc. A known + * value (previously allocated dynamic UPAR for tunnel_type) means + * realloc. Will fail if a realloc is for previously allocated FID, */ uint8_t subtype; /* Describes the type of tracking id to be used */ @@ -52912,17 +57902,28 @@ typedef struct hwrm_tfc_idx_tbl_alloc_set_input { /* Tracked by function id */ #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_TRACK_TYPE_LAST HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_TRACK_TYPE_TRACK_TYPE_FID - /* Reserved */ - uint8_t unused0; + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_LAST HWRM_TFC_IDX_TBL_ALLOC_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE /* The size of the index table entry in bytes. */ uint16_t data_size; + /* Reserved */ + uint8_t unused1[6]; /* The location of the dma buffer */ uint64_t dma_addr; /* - * Index table data located at offset 0. If dma bit is set, + * Index table data located at offset 0. If dma bit is set, * then this field contains the DMA buffer pointer. */ - uint8_t dev_data[104]; + uint8_t dev_data[96]; } hwrm_tfc_idx_tbl_alloc_set_input_t, *phwrm_tfc_idx_tbl_alloc_set_input_t; /* hwrm_tfc_idx_tbl_alloc_set_output (size:128b/16B) */ @@ -53010,6 +58011,15 @@ typedef struct hwrm_tfc_idx_tbl_set_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ @@ -53021,13 +58031,26 @@ typedef struct hwrm_tfc_idx_tbl_set_input { uint16_t idx_tbl_id; /* The size of the index table entry in bytes. */ uint16_t data_size; + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP gparse block type */ + #define HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_LAST HWRM_TFC_IDX_TBL_SET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE + /* unused. */ + uint8_t unused0[5]; /* The location of the dma buffer */ uint64_t dma_addr; /* - * Index table data located at offset 0. If dma bit is set, + * Index table data located at offset 0. If dma bit is set, * then this field contains the DMA buffer pointer. */ - uint8_t dev_data[104]; + uint8_t dev_data[96]; } hwrm_tfc_idx_tbl_set_input_t, *phwrm_tfc_idx_tbl_set_input_t; /* hwrm_tfc_idx_tbl_set_output (size:128b/16B) */ @@ -53059,7 +58082,7 @@ typedef struct hwrm_tfc_idx_tbl_set_output { ************************/ -/* hwrm_tfc_idx_tbl_get_input (size:256b/32B) */ +/* hwrm_tfc_idx_tbl_get_input (size:320b/40B) */ typedef struct hwrm_tfc_idx_tbl_get_input { /* The HWRM command request type. */ @@ -53110,6 +58133,15 @@ typedef struct hwrm_tfc_idx_tbl_get_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ @@ -53121,6 +58153,19 @@ typedef struct hwrm_tfc_idx_tbl_get_input { uint16_t idx_tbl_id; /* The size of the index table entry buffer in bytes. */ uint16_t buffer_size; + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP block type */ + #define HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE gparse block type */ + #define HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE gparse block type */ + #define HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_LAST HWRM_TFC_IDX_TBL_GET_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE + /* unused. */ + uint8_t unused0[5]; /* The location of the response dma buffer */ uint64_t dma_addr; } hwrm_tfc_idx_tbl_get_input_t, *phwrm_tfc_idx_tbl_get_input_t; @@ -53156,7 +58201,7 @@ typedef struct hwrm_tfc_idx_tbl_get_output { *************************/ -/* hwrm_tfc_idx_tbl_free_input (size:192b/24B) */ +/* hwrm_tfc_idx_tbl_free_input (size:256b/32B) */ typedef struct hwrm_tfc_idx_tbl_free_input { /* The HWRM command request type. */ @@ -53202,14 +58247,34 @@ typedef struct hwrm_tfc_idx_tbl_free_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ uint16_t sid; /* Index table id to be freed by the firmware. */ uint16_t idx_tbl_id; - /* Reserved */ - uint8_t unused0[2]; + /* Specifies which block this idx table alloc request is for */ + uint8_t blktype; + /* CFA block type */ + #define HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_BLKTYPE_CFA UINT32_C(0x0) + /* RXP block type */ + #define HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_BLKTYPE_RXP UINT32_C(0x1) + /* RE parse block type */ + #define HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_BLKTYPE_RE_GPARSE UINT32_C(0x2) + /* TE parse block type */ + #define HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE UINT32_C(0x3) + #define HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_LAST HWRM_TFC_IDX_TBL_FREE_INPUT_BLKTYPE_BLKTYPE_TE_GPARSE + /* unused. */ + uint8_t unused0[7]; } hwrm_tfc_idx_tbl_free_input_t, *phwrm_tfc_idx_tbl_free_input_t; /* hwrm_tfc_idx_tbl_free_output (size:128b/16B) */ @@ -53300,6 +58365,15 @@ typedef struct hwrm_tfc_global_id_alloc_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; /* Firmware session id returned when HWRM_TF_SESSION_OPEN is sent. */ uint16_t sid; /* Global domain id. */ @@ -53310,8 +58384,6 @@ typedef struct hwrm_tfc_global_id_alloc_input { * request entries. */ uint16_t req_cnt; - /* unused. */ - uint8_t unused0[2]; /* * This is the DMA address for the request input data array * buffer. Array is of tfc_global_id_hwrm_req type. Size of the @@ -53398,6 +58470,15 @@ typedef struct hwrm_tfc_tcam_set_input { */ uint64_t resp_addr; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ @@ -53425,7 +58506,7 @@ typedef struct hwrm_tfc_tcam_set_input { */ uint8_t subtype; /* unused. */ - uint8_t unused0[6]; + uint8_t unused0[4]; /* The location of the response dma buffer */ uint64_t dma_addr; /* @@ -53452,7 +58533,7 @@ typedef struct hwrm_tfc_tcam_set_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -53510,14 +58591,21 @@ typedef struct hwrm_tfc_tcam_get_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ uint16_t sid; /* Logical TCAM ID. */ uint16_t tcam_id; - /* unused. */ - uint8_t unused0[2]; } hwrm_tfc_tcam_get_input_t, *phwrm_tfc_tcam_get_input_t; /* hwrm_tfc_tcam_get_output (size:2368b/296B) */ @@ -53548,7 +58636,7 @@ typedef struct hwrm_tfc_tcam_get_output { * This field is used in Output records to indicate that the * output is completely written to RAM. This field should be * read as '1' to indicate that the output has been - * completely written. When writing a command completion or + * completely written. When writing a command completion or * response to an internal processor, the order of writes has * to be such that this field is written last. */ @@ -53606,6 +58694,15 @@ typedef struct hwrm_tfc_tcam_alloc_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session id for the session created by the * firmware. Will be used to track this index table entry * only if track type is track_type_sid. @@ -53625,7 +58722,7 @@ typedef struct hwrm_tfc_tcam_alloc_input { #define HWRM_TFC_TCAM_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) #define HWRM_TFC_TCAM_ALLOC_INPUT_TRACK_TYPE_LAST HWRM_TFC_TCAM_ALLOC_INPUT_TRACK_TYPE_TRACK_TYPE_FID /* Unused. */ - uint8_t unused0[7]; + uint8_t unused0[5]; } hwrm_tfc_tcam_alloc_input_t, *phwrm_tfc_tcam_alloc_input_t; /* hwrm_tfc_tcam_alloc_output (size:128b/16B) */ @@ -53710,6 +58807,15 @@ typedef struct hwrm_tfc_tcam_alloc_set_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Unique session id for the session created by the * firmware. Will be used to track this index table entry * only if track type is track_type_sid. @@ -53731,11 +58837,11 @@ typedef struct hwrm_tfc_tcam_alloc_set_input { #define HWRM_TFC_TCAM_ALLOC_SET_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) #define HWRM_TFC_TCAM_ALLOC_SET_INPUT_TRACK_TYPE_LAST HWRM_TFC_TCAM_ALLOC_SET_INPUT_TRACK_TYPE_TRACK_TYPE_FID /* Unused */ - uint8_t unused[5]; + uint8_t unused[3]; /* The location of the response dma buffer */ uint64_t dma_addr; /* - * Index table data located at offset 0. If dma bit is set, + * Index table data located at offset 0. If dma bit is set, * then this field contains the DMA buffer pointer. */ uint8_t dev_data[96]; @@ -53818,14 +58924,21 @@ typedef struct hwrm_tfc_tcam_free_input { */ uint8_t subtype; /* + * Function ID. + * If running on a trusted VF or PF, the fid field can be used to + * specify that the function is a non-trusted VF of the parent PF. + * If this command is used for the target_id itself, this field is + * set to 0xffff. A non-trusted VF cannot specify a valid FID in this + * field. + */ + uint16_t fid; + /* * Session id associated with the firmware. Will be used * for validation if the track type matches. */ uint16_t sid; /* Logical TCAM ID. */ uint16_t tcam_id; - /* Reserved */ - uint8_t unused0[2]; } hwrm_tfc_tcam_free_input_t, *phwrm_tfc_tcam_free_input_t; /* hwrm_tfc_tcam_free_output (size:128b/16B) */ @@ -53852,6 +58965,371 @@ typedef struct hwrm_tfc_tcam_free_output { uint8_t valid; } hwrm_tfc_tcam_free_output_t, *phwrm_tfc_tcam_free_output_t; +/*********************** + * hwrm_tfc_if_tbl_set * + ***********************/ + + +/* hwrm_tfc_if_tbl_set_input (size:960b/120B) */ + +typedef struct hwrm_tfc_if_tbl_set_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Session identifier. */ + uint16_t sid; + /* Function identifier. */ + uint16_t fid; + /* + * Subtype identifying IF table type. See + * cfa_v3/include/cfa_resources.h. + */ + uint8_t subtype; + /* Control flags. */ + uint8_t flags; + /* Indicates the flow direction. */ + #define HWRM_TFC_IF_TBL_SET_INPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TFC_IF_TBL_SET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TFC_IF_TBL_SET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TFC_IF_TBL_SET_INPUT_FLAGS_DIR_LAST HWRM_TFC_IF_TBL_SET_INPUT_FLAGS_DIR_TX + /* Table entry index. */ + uint16_t index; + /* Size of data in data field. */ + uint8_t data_size; + /* Reserved */ + uint8_t unused0[7]; + /* Table data. */ + uint8_t data[88]; +} hwrm_tfc_if_tbl_set_input_t, *phwrm_tfc_if_tbl_set_input_t; + +/* hwrm_tfc_if_tbl_set_output (size:128b/16B) */ + +typedef struct hwrm_tfc_if_tbl_set_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Reserved */ + uint8_t unused0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tfc_if_tbl_set_output_t, *phwrm_tfc_if_tbl_set_output_t; + +/*********************** + * hwrm_tfc_if_tbl_get * + ***********************/ + + +/* hwrm_tfc_if_tbl_get_input (size:256b/32B) */ + +typedef struct hwrm_tfc_if_tbl_get_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Session identifier. */ + uint16_t sid; + /* Function identifier. */ + uint16_t fid; + /* + * Subtype identifying IF table type. See + * cfa_v3/include/cfa_resources.h. + */ + uint8_t subtype; + /* Control flags. */ + uint8_t flags; + /* Indicates the flow direction. */ + #define HWRM_TFC_IF_TBL_GET_INPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TFC_IF_TBL_GET_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TFC_IF_TBL_GET_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TFC_IF_TBL_GET_INPUT_FLAGS_DIR_LAST HWRM_TFC_IF_TBL_GET_INPUT_FLAGS_DIR_TX + /* Table entry index. */ + uint16_t index; + /* Size of data in data field. */ + uint8_t data_size; + /* Reserved */ + uint8_t unused0[7]; +} hwrm_tfc_if_tbl_get_input_t, *phwrm_tfc_if_tbl_get_input_t; + +/* hwrm_tfc_if_tbl_get_output (size:960b/120B) */ + +typedef struct hwrm_tfc_if_tbl_get_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Session identifier. */ + uint16_t sid; + /* Function identifier. */ + uint16_t fid; + /* + * Subtype identifying IF table type. See + * cfa_v3/include/cfa_resources.h. + */ + uint8_t subtype; + /* Control flags. */ + uint8_t flags; + /* Indicates the flow direction. */ + #define HWRM_TFC_IF_TBL_GET_OUTPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TFC_IF_TBL_GET_OUTPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TFC_IF_TBL_GET_OUTPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TFC_IF_TBL_GET_OUTPUT_FLAGS_DIR_LAST HWRM_TFC_IF_TBL_GET_OUTPUT_FLAGS_DIR_TX + /* Table entry index. */ + uint16_t index; + /* Size of data in data field. */ + uint8_t data_size; + /* Reserved */ + uint8_t unused0[7]; + /* Table data. */ + uint8_t data[88]; + /* Reserved */ + uint8_t unused1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tfc_if_tbl_get_output_t, *phwrm_tfc_if_tbl_get_output_t; + +/********************************* + * hwrm_tfc_tbl_scope_config_get * + *********************************/ + + +/* TruFlow command to return whether the table scope is fully configured. */ +/* hwrm_tfc_tbl_scope_config_get_input (size:192b/24B) */ + +typedef struct hwrm_tfc_tbl_scope_config_get_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* The table scope ID. */ + uint8_t tsid; + /* unused. */ + uint8_t unused0[7]; +} hwrm_tfc_tbl_scope_config_get_input_t, *phwrm_tfc_tbl_scope_config_get_input_t; + +/* hwrm_tfc_tbl_scope_config_get_output (size:128b/16B) */ + +typedef struct hwrm_tfc_tbl_scope_config_get_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* If set to 1, the table scope is configured. */ + uint8_t configured; + /* unused. */ + uint8_t unused0[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tfc_tbl_scope_config_get_output_t, *phwrm_tfc_tbl_scope_config_get_output_t; + +/***************************** + * hwrm_tfc_resc_usage_query * + *****************************/ + + +/* hwrm_tfc_resc_usage_query_input (size:256b/32B) */ + +typedef struct hwrm_tfc_resc_usage_query_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Session identifier. */ + uint16_t sid; + /* Function identifier. */ + uint16_t fid; + /* Control flags. */ + uint8_t flags; + /* Indicates the flow direction. */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_FLAGS_DIR UINT32_C(0x1) + /* If this bit set to 0, then it indicates rx flow. */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_RX UINT32_C(0x0) + /* If this bit is set to 1, then it indicates tx flow. */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_TX UINT32_C(0x1) + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_LAST HWRM_TFC_RESC_USAGE_QUERY_INPUT_FLAGS_DIR_TX + /* Describes the type of tracking id to be used */ + uint8_t track_type; + /* Invalid track type */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_TRACK_TYPE_TRACK_TYPE_INVALID UINT32_C(0x0) + /* Tracked by session id */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_TRACK_TYPE_TRACK_TYPE_SID UINT32_C(0x1) + /* Tracked by function id */ + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_TRACK_TYPE_TRACK_TYPE_FID UINT32_C(0x2) + #define HWRM_TFC_RESC_USAGE_QUERY_INPUT_TRACK_TYPE_LAST HWRM_TFC_RESC_USAGE_QUERY_INPUT_TRACK_TYPE_TRACK_TYPE_FID + /* Size of data in data field. */ + uint16_t data_size; + /* unused */ + uint8_t unused1[8]; +} hwrm_tfc_resc_usage_query_input_t, *phwrm_tfc_resc_usage_query_input_t; + +/* hwrm_tfc_resc_usage_query_output (size:960b/120B) */ + +typedef struct hwrm_tfc_resc_usage_query_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Response code. */ + uint32_t resp_code; + /* Size of data in data field. */ + uint16_t data_size; + /* unused */ + uint16_t unused0; + /* Response data. */ + uint8_t data[96]; + /* unused */ + uint8_t unused1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field + * is written last. + */ + uint8_t valid; +} hwrm_tfc_resc_usage_query_output_t, *phwrm_tfc_resc_usage_query_output_t; + /****************************** * hwrm_tunnel_dst_port_query * ******************************/ @@ -53891,27 +59369,56 @@ typedef struct hwrm_tunnel_dst_port_query_input { /* Tunnel Type. */ uint8_t tunnel_type; /* Virtual eXtensible Local Area Network (VXLAN) */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) /* Generic Network Virtualization Encapsulation (Geneve) */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) /* IPV4 over virtual eXtensible Local Area Network (IPV4oVXLAN) */ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN_V4 UINT32_C(0x9) - /* Enhance Generic Routing Encapsulation (GRE version 1) inside IP datagram payload */ + /* + * Enhance Generic Routing Encapsulation (GRE version 1) inside IP + * datagram payload + */ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_IPGRE_V1 UINT32_C(0xa) /* Use fixed layer 2 ether type of 0xFFFF */ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_L2_ETYPE UINT32_C(0xb) - /* IPV6 over virtual eXtensible Local Area Network with GPE header (IPV6oVXLANGPE) */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) + /* + * IPV6 over virtual eXtensible Local Area Network with GPE header + * (IPV6oVXLANGPE) + */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) /* Custom GRE uses UPAR to parse customized GRE packets */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) /* Enhanced Common Packet Radio Interface (eCPRI) */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) /* IPv6 Segment Routing (SRv6) */ - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) /* Generic Protocol Extension for VXLAN (VXLAN-GPE) */ #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN_GPE UINT32_C(0x10) - #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN_GPE - uint8_t unused_0[7]; + /* Generic Routing Encapsulation */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_GRE UINT32_C(0x11) + /* ULP Dynamic UPAR tunnel */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR UINT32_C(0x12) + /* ULP Dynamic UPAR tunnel reserved 1 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES01 UINT32_C(0x13) + /* ULP Dynamic UPAR tunnel reserved 2 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES02 UINT32_C(0x14) + /* ULP Dynamic UPAR tunnel reserved 3 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES03 UINT32_C(0x15) + /* ULP Dynamic UPAR tunnel reserved 4 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES04 UINT32_C(0x16) + /* ULP Dynamic UPAR tunnel reserved 5 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES05 UINT32_C(0x17) + /* ULP Dynamic UPAR tunnel reserved 6 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES06 UINT32_C(0x18) + /* ULP Dynamic UPAR tunnel reserved 7 */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 UINT32_C(0x19) + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 + /* + * This field is used to specify the next protocol value defined in the + * corresponding RFC spec for the applicable tunnel type. + */ + uint8_t tunnel_next_proto; + uint8_t unused_0[6]; } hwrm_tunnel_dst_port_query_input_t, *phwrm_tunnel_dst_port_query_input_t; /* hwrm_tunnel_dst_port_query_output (size:128b/16B) */ @@ -53966,12 +59473,24 @@ typedef struct hwrm_tunnel_dst_port_query_output { #define HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR6 UINT32_C(0x40) /* This bit will be '1' when UPAR7 is IN_USE */ #define HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR7 UINT32_C(0x80) - uint8_t unused_0[2]; + /* + * This field is used to convey the status of non udp port based + * tunnel parsing at chip level and at function level. + */ + uint8_t status; + /* This bit will be '1' when tunnel parsing is enabled globally. */ + #define HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_STATUS_CHIP_LEVEL UINT32_C(0x1) + /* + * This bit will be '1' when tunnel parsing is enabled + * on the corresponding function. + */ + #define HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_STATUS_FUNC_LEVEL UINT32_C(0x2) + uint8_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54016,27 +59535,58 @@ typedef struct hwrm_tunnel_dst_port_alloc_input { /* Tunnel Type. */ uint8_t tunnel_type; /* Virtual eXtensible Local Area Network (VXLAN) */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) /* Generic Network Virtualization Encapsulation (Geneve) */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) /* IPV4 over virtual eXtensible Local Area Network (IPV4oVXLAN) */ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4 UINT32_C(0x9) - /* Enhance Generic Routing Encapsulation (GRE version 1) inside IP datagram payload */ + /* + * Enhance Generic Routing Encapsulation (GRE version 1) inside IP + * datagram payload + */ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_IPGRE_V1 UINT32_C(0xa) /* Use fixed layer 2 ether type of 0xFFFF */ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_L2_ETYPE UINT32_C(0xb) - /* IPV6 over virtual eXtensible Local Area Network with GPE header (IPV6oVXLANGPE) */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) - /* Custom GRE uses UPAR to parse customized GRE packets. This is not supported. */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) + /* + * IPV6 over virtual eXtensible Local Area Network with GPE header + * (IPV6oVXLANGPE) + */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) + /* + * Custom GRE uses UPAR to parse customized GRE packets. This is not + * supported. + */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) /* Enhanced Common Packet Radio Interface (eCPRI) */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) /* IPv6 Segment Routing (SRv6) */ - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) /* Generic Protocol Extension for VXLAN (VXLAN-GPE) */ #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_GPE UINT32_C(0x10) - #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_GPE - uint8_t unused_0; + /* Generic Routing Encapsulation */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GRE UINT32_C(0x11) + /* ULP Dynamic UPAR tunnel */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR UINT32_C(0x12) + /* ULP Dynamic UPAR tunnel reserved 1 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES01 UINT32_C(0x13) + /* ULP Dynamic UPAR tunnel reserved 2 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES02 UINT32_C(0x14) + /* ULP Dynamic UPAR tunnel reserved 3 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES03 UINT32_C(0x15) + /* ULP Dynamic UPAR tunnel reserved 4 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES04 UINT32_C(0x16) + /* ULP Dynamic UPAR tunnel reserved 5 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES05 UINT32_C(0x17) + /* ULP Dynamic UPAR tunnel reserved 6 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES06 UINT32_C(0x18) + /* ULP Dynamic UPAR tunnel reserved 7 */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 UINT32_C(0x19) + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 + /* + * This field is used to specify the next protocol value defined in the + * corresponding RFC spec for the applicable tunnel type. + */ + uint8_t tunnel_next_proto; /* * This field represents the value of L4 destination port used * for the given tunnel type. This field is valid for @@ -54048,7 +59598,7 @@ typedef struct hwrm_tunnel_dst_port_alloc_input { * A value of 0 shall fail the command. */ uint16_t tunnel_dst_port_val; - uint8_t unused_1[4]; + uint8_t unused_0[4]; } hwrm_tunnel_dst_port_alloc_input_t, *phwrm_tunnel_dst_port_alloc_input_t; /* hwrm_tunnel_dst_port_alloc_output (size:128b/16B) */ @@ -54063,8 +59613,8 @@ typedef struct hwrm_tunnel_dst_port_alloc_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * Identifier of a tunnel L4 destination port value. Only applies to tunnel - * types that has l4 destination port parameters. + * Identifier of a tunnel L4 destination port value. Only applies to + * tunnel types that has l4 destination port parameters. */ uint16_t tunnel_dst_port_id; /* Error information */ @@ -54075,7 +59625,9 @@ typedef struct hwrm_tunnel_dst_port_alloc_output { #define HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_ALLOCATED UINT32_C(0x1) /* Out of resources error */ #define HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_NO_RESOURCE UINT32_C(0x2) - #define HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_LAST HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_NO_RESOURCE + /* Tunnel type is already enabled */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_ENABLED UINT32_C(0x3) + #define HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_LAST HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_ENABLED /* * This field represents the UPAR usage status. * Available UPARs on wh+ are UPAR0 and UPAR1 @@ -54102,9 +59654,9 @@ typedef struct hwrm_tunnel_dst_port_alloc_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54149,33 +59701,64 @@ typedef struct hwrm_tunnel_dst_port_free_input { /* Tunnel Type. */ uint8_t tunnel_type; /* Virtual eXtensible Local Area Network (VXLAN) */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) /* Generic Network Virtualization Encapsulation (Geneve) */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) /* IPV4 over virtual eXtensible Local Area Network (IPV4oVXLAN) */ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN_V4 UINT32_C(0x9) - /* Enhance Generic Routing Encapsulation (GRE version 1) inside IP datagram payload */ + /* + * Enhance Generic Routing Encapsulation (GRE version 1) inside IP + * datagram payload + */ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_IPGRE_V1 UINT32_C(0xa) /* Use fixed layer 2 ether type of 0xFFFF */ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_L2_ETYPE UINT32_C(0xb) - /* IPV6 over virtual eXtensible Local Area Network with GPE header (IPV6oVXLANGPE) */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) - /* Custom GRE uses UPAR to parse customized GRE packets. This is not supported. */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) + /* + * IPV6 over virtual eXtensible Local Area Network with GPE header + * (IPV6oVXLANGPE) + */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6 UINT32_C(0xc) + /* + * Custom GRE uses UPAR to parse customized GRE packets. This is not + * supported. + */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_CUSTOM_GRE UINT32_C(0xd) /* Enhanced Common Packet Radio Interface (eCPRI) */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ECPRI UINT32_C(0xe) /* IPv6 Segment Routing (SRv6) */ - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_SRV6 UINT32_C(0xf) /* Generic Protocol Extension for VXLAN (VXLAN-GPE) */ #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN_GPE UINT32_C(0x10) - #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN_GPE - uint8_t unused_0; - /* - * Identifier of a tunnel L4 destination port value. Only applies to tunnel - * types that has l4 destination port parameters. + /* Generic Routing Encapsulation */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_GRE UINT32_C(0x11) + /* ULP Dynamic UPAR tunnel */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR UINT32_C(0x12) + /* ULP Dynamic UPAR tunnel reserved 1 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES01 UINT32_C(0x13) + /* ULP Dynamic UPAR tunnel reserved 2 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES02 UINT32_C(0x14) + /* ULP Dynamic UPAR tunnel reserved 3 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES03 UINT32_C(0x15) + /* ULP Dynamic UPAR tunnel reserved 4 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES04 UINT32_C(0x16) + /* ULP Dynamic UPAR tunnel reserved 5 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES05 UINT32_C(0x17) + /* ULP Dynamic UPAR tunnel reserved 6 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES06 UINT32_C(0x18) + /* ULP Dynamic UPAR tunnel reserved 7 */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 UINT32_C(0x19) + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_LAST HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_ULP_DYN_UPAR_RES07 + /* + * This field is used to specify the next protocol value defined in the + * corresponding RFC spec for the applicable tunnel type. + */ + uint8_t tunnel_next_proto; + /* + * Identifier of a tunnel L4 destination port value. Only applies to + * tunnel types that has l4 destination port parameters. */ uint16_t tunnel_dst_port_id; - uint8_t unused_1[4]; + uint8_t unused_0[4]; } hwrm_tunnel_dst_port_free_input_t, *phwrm_tunnel_dst_port_free_input_t; /* hwrm_tunnel_dst_port_free_output (size:128b/16B) */ @@ -54201,9 +59784,9 @@ typedef struct hwrm_tunnel_dst_port_free_output { uint8_t unused_1[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54361,7 +59944,7 @@ typedef struct ctx_eng_stats { ***********************/ -/* hwrm_stat_ctx_alloc_input (size:256b/32B) */ +/* hwrm_stat_ctx_alloc_input (size:384b/48B) */ typedef struct hwrm_stat_ctx_alloc_input { /* The HWRM command request type. */ @@ -54425,7 +60008,19 @@ typedef struct hwrm_stat_ctx_alloc_input { * When this bit is set to '0', the statistics context shall be * used for network traffic or engine traffic. */ - #define HWRM_STAT_CTX_ALLOC_INPUT_STAT_CTX_FLAGS_ROCE UINT32_C(0x1) + #define HWRM_STAT_CTX_ALLOC_INPUT_STAT_CTX_FLAGS_ROCE UINT32_C(0x1) + /* + * When this bit is set to '1', the PF is requesting a duplicate + * host buffer used for VF statistics. The stat_ctx_id and + * alloc_seq_id fields must be populated when this bit is set to + * '1'. The stat_ctx_id indicates the VF statistics context that + * should be copied to this host buffer. The stat_ctx_id and + * alloc_seq_id should be copied from the vf_stat_change event + * received by the PF. This bit can only be set for a PF. An error + * is returned if a VF sets this bit. This bit is only supported if + * vf_stat_ejection_supported is '1' in func_qcaps. + */ + #define HWRM_STAT_CTX_ALLOC_INPUT_STAT_CTX_FLAGS_DUP_HOST_BUF UINT32_C(0x2) uint8_t unused_0; /* * This is the size of the structure (ctx_hw_stats or @@ -54433,6 +60028,27 @@ typedef struct hwrm_stat_ctx_alloc_input { * for the periodic DMA updates. */ uint16_t stats_dma_length; + uint16_t flags; + /* This stats context uses the steering tag specified in the command. */ + #define HWRM_STAT_CTX_ALLOC_INPUT_FLAGS_STEERING_TAG_VALID UINT32_C(0x1) + /* + * Steering tag to use for memory transactions from the periodic DMA + * updates. 'steering_tag_valid' should be set and 'steering_tag' + * should be specified, when the 'steering_tag_supported' bit is set + * under the 'flags_ext2' field of the hwrm_func_qcaps_output. + */ + uint16_t steering_tag; + /* + * Only valid when dup_host_buf is '1'. This value should be copied + * from the vf_stat_change event. + */ + uint32_t stat_ctx_id; + /* + * Only valid when dup_host_buf is '1'. This value should be copied + * from the vf_stat_change event. + */ + uint16_t alloc_seq_id; + uint8_t unused_1[6]; } hwrm_stat_ctx_alloc_input_t, *phwrm_stat_ctx_alloc_input_t; /* hwrm_stat_ctx_alloc_output (size:128b/16B) */ @@ -54451,9 +60067,9 @@ typedef struct hwrm_stat_ctx_alloc_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54516,9 +60132,9 @@ typedef struct hwrm_stat_ctx_free_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54626,9 +60242,9 @@ typedef struct hwrm_stat_ctx_query_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54740,9 +60356,9 @@ typedef struct hwrm_stat_ext_ctx_query_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54844,9 +60460,9 @@ typedef struct hwrm_stat_ctx_eng_query_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54907,9 +60523,9 @@ typedef struct hwrm_stat_ctx_clr_stats_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -54981,9 +60597,9 @@ typedef struct hwrm_pcie_qstats_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -55066,7 +60682,7 @@ typedef struct hwrm_stat_generic_qstats_input { * The size of the generic statistics buffer passed in the * generic_stat_host_addr in bytes. * Firmware will not exceed this size when it DMAs the - * statistics structure to the host. The actual DMA size + * statistics structure to the host. The actual DMA size * will be returned in the response. */ uint16_t generic_stat_size; @@ -55101,7 +60717,7 @@ typedef struct hwrm_stat_generic_qstats_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -55111,7 +60727,7 @@ typedef struct hwrm_stat_generic_qstats_output { } hwrm_stat_generic_qstats_output_t, *phwrm_stat_generic_qstats_output_t; /* Generic Statistic Format */ -/* generic_sw_hw_stats (size:1408b/176B) */ +/* generic_sw_hw_stats (size:1472b/184B) */ typedef struct generic_sw_hw_stats { /* @@ -55156,34 +60772,34 @@ typedef struct generic_sw_hw_stats { /* Available completion flow control data credits. */ uint64_t pcie_credit_fc_cmpl_data_posted; /* - * Displays Time information of the longest completon time from any of - * the 4 tags for the caller PF. The unit of time recorded is in + * Displays Time information of the longest completion time from any of + * the 4 tags for the caller PF. The unit of time recorded is in * microseconds. */ uint64_t pcie_cmpl_longest; /* - * Displays Time information of the shortest completon time from any of - * the 4 tags for the caller PF. The unit of time recorded is in + * Displays Time information of the shortest completion time from any + * of the 4 tags for the caller PF. The unit of time recorded is in * microseconds. */ uint64_t pcie_cmpl_shortest; /* - * This field containts the total number of CFCQ 'misses' observed for + * This field contains the total number of CFCQ 'misses' observed for * all the PF's. */ uint64_t cache_miss_count_cfcq; /* - * This field containts the total number of CFCS 'misses' observed for + * This field contains the total number of CFCS 'misses' observed for * all the PF's. */ uint64_t cache_miss_count_cfcs; /* - * This field containts the total number of CFCC 'misses' observed for + * This field contains the total number of CFCC 'misses' observed for * all the PF's. */ uint64_t cache_miss_count_cfcc; /* - * This field containts the total number of CFCM 'misses' observed + * This field contains the total number of CFCM 'misses' observed * for all the PF's. */ uint64_t cache_miss_count_cfcm; @@ -55205,8 +60821,107 @@ typedef struct generic_sw_hw_stats { * the hardware based doorbell drop recovery feature. */ uint64_t hw_db_recov_dbs_recovered; + /* + * Total number of out of order doorbell messages dropped. + * This counter is only applicable for devices that support + * the hardware based doorbell drop recovery feature. + */ + uint64_t hw_db_recov_oo_drop_count; } generic_sw_hw_stats_t, *pgeneric_sw_hw_stats_t; +/***************************** + * hwrm_stat_db_error_qstats * + *****************************/ + + +/* hwrm_stat_db_error_qstats_input (size:128b/16B) */ + +typedef struct hwrm_stat_db_error_qstats_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_stat_db_error_qstats_input_t, *phwrm_stat_db_error_qstats_input_t; + +/* hwrm_stat_db_error_qstats_output (size:320b/40B) */ + +typedef struct hwrm_stat_db_error_qstats_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * Specifies count of doorbells dropped due to RoCE SQs or L2 + * Tx Rings being in invalid state. + */ + uint32_t tx_db_drop_invalid_qp_state; + /* + * Specifies count of doorbells dropped due to RoCE RQs/SRQs or + * L2 Rx Rings being used in invalid state. + */ + uint32_t rx_db_drop_invalid_rq_state; + /* + * Specifies count of doorbells dropped for any doorbell type + * due to formatting errors such as illegal doorbell message + * type, index out of range etc. + */ + uint32_t tx_db_drop_format_error; + /* + * Specifies count of express mode doorbells dropped for any + * doorbell type due to error conditions such as DPI check, + * context load error etc. + */ + uint32_t express_db_dropped_misc_error; + /* + * Specifies count of express mode doorbells dropped due to + * RoCE SQ overflow. + */ + uint32_t express_db_dropped_sq_overflow; + /* + * Specifies count of express mode doorbells dropped due to + * RoCE RQ overflow. + */ + uint32_t express_db_dropped_rq_overflow; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field is + * written last. + */ + uint8_t valid; +} hwrm_stat_db_error_qstats_output_t, *phwrm_stat_db_error_qstats_output_t; + /***************** * hwrm_fw_reset * *****************/ @@ -55254,8 +60969,8 @@ typedef struct hwrm_fw_reset_input { /* RoCE control processor */ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3) /* - * Host (in multi-host environment): This is only valid if requester is IPC. - * Reinit host hardware resources and PCIe. + * Host (in multi-host environment): This is only valid if requester + * is IPC. Reinit host hardware resources and PCIe. */ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_HOST UINT32_C(0x4) /* @@ -55266,17 +60981,17 @@ typedef struct hwrm_fw_reset_input { /* Reset all blocks of the chip (including all processors) */ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_CHIP UINT32_C(0x6) /* - * Host (in multi-host environment): This is only valid if requester is IPC. - * Reinit host hardware resources. + * Host (in multi-host environment): This is only valid if requester + * is IPC. Reinit host hardware resources. */ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_HOST_RESOURCE_REINIT UINT32_C(0x7) /* - * Activate firmware that has been programmed to NVM. The + * Activate firmware that has been programmed to NVM. The * activation is done in an impactless manner as part of the scheme * where hwrm_fw_state_backup precedes the call, and - * hwrm_fw_state_restore follows it. Before this call returns, FW + * hwrm_fw_state_restore follows it. Before this call returns, FW * status is set to a non-0x8000 value to disambiguate reset pending - * from reset complete. The reset process begins after this call + * from reset complete. The reset process begins after this call * returns to ensure this HWRM has completed before reset begins. */ #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_IMPACTLESS_ACTIVATION UINT32_C(0x8) @@ -55301,8 +61016,9 @@ typedef struct hwrm_fw_reset_input { uint8_t flags; /* * When this bit is '1', then the core firmware initiates - * the reset only after graceful shut down of all registered instances. - * If not, the device will continue with the existing firmware. + * the reset only after graceful shut down of all registered + * instances. If not, the device will continue with the existing + * firmware. */ #define HWRM_FW_RESET_INPUT_FLAGS_RESET_GRACEFUL UINT32_C(0x1) /* @@ -55340,9 +61056,9 @@ typedef struct hwrm_fw_reset_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -55394,9 +61110,15 @@ typedef struct hwrm_fw_qstatus_input { #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_NETCTRL UINT32_C(0x2) /* RoCE control processor */ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3) - /* Host (in multi-host environment): This is only valid if requester is IPC */ + /* + * Host (in multi-host environment): This is only valid if requester + * is IPC + */ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_HOST UINT32_C(0x4) - /* AP processor complex (in multi-host environment). Use host_idx to control which core is reset */ + /* + * AP processor complex (in multi-host environment). Use host_idx to + * control which core is reset + */ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_AP UINT32_C(0x5) /* Reset all blocks of the chip (including all processors) */ #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_CHIP UINT32_C(0x6) @@ -55444,9 +61166,9 @@ typedef struct hwrm_fw_qstatus_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -55530,9 +61252,9 @@ typedef struct hwrm_fw_set_time_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -55615,9 +61337,9 @@ typedef struct hwrm_fw_get_time_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -55638,12 +61360,20 @@ typedef struct hwrm_struct_hdr { #define HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP UINT32_C(0x421) /* DCBX state configuration structured data ID for all DCBX features. */ #define HWRM_STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE UINT32_C(0x422) - /* LLDP generic structured data ID. This is used with GET_STRUCTURED_DATA only. */ + /* + * LLDP generic structured data ID. This is used with + * GET_STRUCTURED_DATA only. + */ #define HWRM_STRUCT_HDR_STRUCT_ID_LLDP_GENERIC UINT32_C(0x424) - /* LLDP device structured data ID. This is used with GET_STRUCTURED_DATA only. */ + /* + * LLDP device structured data ID. This is used with + * GET_STRUCTURED_DATA only. + */ #define HWRM_STRUCT_HDR_STRUCT_ID_LLDP_DEVICE UINT32_C(0x426) /* Power Backup info */ #define HWRM_STRUCT_HDR_STRUCT_ID_POWER_BKUP UINT32_C(0x427) + /* Guest physical address to Host physical address mapping */ + #define HWRM_STRUCT_HDR_STRUCT_ID_PEER_MMAP UINT32_C(0x429) /* reserved for AFM usage. */ #define HWRM_STRUCT_HDR_STRUCT_ID_AFM_OPAQUE UINT32_C(0x1) /* Port description. */ @@ -55662,9 +61392,9 @@ typedef struct hwrm_struct_hdr { /* This value indicates the subtype. */ uint16_t subtype; /* - * This value indicates the count of 64-bit values that point to the next header. - * A value of 0 means that this is the last element. The value is a count of 64-bit - * words from the beginning of the current header. + * This value indicates the count of 64-bit values that point to the next + * header. A value of 0 means that this is the last element. The value is + * a count of 64-bit words from the beginning of the current header. */ uint16_t next_offset; /* This value indicates this is the last element */ @@ -55676,8 +61406,9 @@ typedef struct hwrm_struct_hdr { typedef struct hwrm_struct_data_dcbx_ets { /* - * This field indicates if this configuration is ETS recommendation or ETS configuration. - * A value 1 means it is ETS configuration, A value of 2 means it is a ETS recommendation. + * This field indicates if this configuration is ETS recommendation or + * ETS configuration. A value 1 means it is ETS configuration, A value of + * 2 means it is a ETS recommendation. */ uint8_t destination; /* ETS configuration */ @@ -55753,8 +61484,9 @@ typedef struct hwrm_struct_data_dcbx_ets { typedef struct hwrm_struct_data_dcbx_pfc { /* - * This field indicates PFC priority bit map. A value of '0' indicates PFC - * is disabled. A value of '1' indicates PFC is enabled on that priority. + * This field indicates PFC priority bit map. A value of '0' indicates + * PFC is disabled. A value of '1' indicates PFC is enabled on that + * priority. */ uint8_t pfc_priority_bitmap; /* @@ -55764,7 +61496,8 @@ typedef struct hwrm_struct_data_dcbx_pfc { uint8_t max_pfc_tcs; /* * This field indicates if MACSec bypass capability is enabled. A value - * of '1' indicates MBC is enabled. A value of '0' indicates MBC is disabled. + * of '1' indicates MBC is enabled. A value of '0' indicates MBC is + * disabled. */ uint8_t mbc; uint8_t unused_0[5]; @@ -55826,7 +61559,10 @@ typedef struct hwrm_struct_data_dcbx_feature_state { #define HWRM_STRUCT_DATA_DCBX_FEATURE_STATE_APP_STATE_LAST HWRM_STRUCT_DATA_DCBX_FEATURE_STATE_APP_STATE_ADVERTISE_BIT_POS /* unused. */ uint8_t unused[3]; - /* This field is used to reset the DCBX configuration to factory defaults. */ + /* + * This field is used to reset the DCBX configuration to factory + * defaults. + */ uint8_t resets; /* reset ETS configuration. */ #define HWRM_STRUCT_DATA_DCBX_FEATURE_STATE_RESETS_RESET_ETS UINT32_C(0x1) @@ -55956,8 +61692,8 @@ typedef struct hwrm_struct_data_lldp_device { typedef struct hwrm_struct_data_port_description { /* - * Port #. Port number starts at 0 and anything greater than number of ports - * minus 1 is an error. + * Port #. Port number starts at 0 and anything greater than number of + * ports minus 1 is an error. */ uint8_t port_id; uint8_t unused_0[7]; @@ -56021,9 +61757,9 @@ typedef struct hwrm_struct_data_power_information { uint32_t bkup_power_info_ver; /* Platform backup power count */ uint32_t platform_bkup_power_count; - /* Load in milli Watt */ + /* Load in milliwatts */ uint32_t load_milli_watt; - /* Backup time in milli seconds */ + /* Backup time in milliseconds */ uint32_t bkup_time_milli_seconds; /* Backup power status */ uint32_t bkup_power_status; @@ -56031,6 +61767,77 @@ typedef struct hwrm_struct_data_power_information { uint32_t bkup_power_charge_time; } hwrm_struct_data_power_information_t, *phwrm_struct_data_power_information_t; +/* + * All mappings (upto 8) for a function will be sent down + * at the same time. If entries are sent down for the same + * function again, the existing saved entries will be + * overwritten. + */ +/* hwrm_struct_data_peer_mmap (size:1600b/200B) */ + +typedef struct hwrm_struct_data_peer_mmap { + /* + * Target function ID for the mappings. The fid should + * be 0xffff for current PF or a valid VF fid for child + * VF of the current PF. + */ + uint16_t fid; + /* + * Number of mappings for this function. The count has to + * be > 0 and <= 8. Maximum of 8 mappings are supported. + */ + uint16_t count; + uint32_t unused_0; + /* Host Physical Address for mapping 0. */ + uint64_t hpa_0; + /* Guest Physical Address for mapping 0. */ + uint64_t gpa_0; + /* Size in Kilobytes for mapping 0. */ + uint64_t size_0; + /* Host Physical Address for mapping 1. */ + uint64_t hpa_1; + /* Guest Physical Address for mapping 1. */ + uint64_t gpa_1; + /* Size in Kilobytes for mapping 1. */ + uint64_t size_1; + /* Host Physical Address for mapping 2. */ + uint64_t hpa_2; + /* Guest Physical Address for mapping 2. */ + uint64_t gpa_2; + /* Size in Kilobytes for mapping 2. */ + uint64_t size_2; + /* Host Physical Address for mapping 3. */ + uint64_t hpa_3; + /* Guest Physical Address for mapping 3. */ + uint64_t gpa_3; + /* Size in Kilobytes for mapping 3. */ + uint64_t size_3; + /* Host Physical Address for mapping 4. */ + uint64_t hpa_4; + /* Guest Physical Address for mapping 4. */ + uint64_t gpa_4; + /* Size in Kilobytes for mapping 4. */ + uint64_t size_4; + /* Host Physical Address for mapping 5. */ + uint64_t hpa_5; + /* Guest Physical Address for mapping 5. */ + uint64_t gpa_5; + /* Size in Kilobytes for mapping 5. */ + uint64_t size_5; + /* Host Physical Address for mapping 6. */ + uint64_t hpa_6; + /* Guest Physical Address for mapping 6. */ + uint64_t gpa_6; + /* Size in Kilobytes for mapping 6. */ + uint64_t size_6; + /* Host Physical Address for mapping 7. */ + uint64_t hpa_7; + /* Guest Physical Address for mapping 7. */ + uint64_t gpa_7; + /* Size in Kilobytes for mapping 7. */ + uint64_t size_7; +} hwrm_struct_data_peer_mmap_t, *phwrm_struct_data_peer_mmap_t; + /* hwrm_struct_data_msix_per_vf (size:320b/40B) */ typedef struct hwrm_struct_data_msix_per_vf { @@ -56138,9 +61945,9 @@ typedef struct hwrm_fw_set_structured_data_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56210,21 +62017,23 @@ typedef struct hwrm_fw_get_structured_data_input { /* size of data in bytes */ uint16_t data_len; /* - * Structure_id is the id of the structure data requesting and count is a - * requested number of instances of this data requested. The actual number - * will be returned in count_of_headers + * Structure_id is the id of the structure data requesting and count is + * a requested number of instances of this data requested. The actual + * number will be returned in count_of_headers */ uint16_t structure_id; /* - * Subtype is an optional field used to specify additional information of the data - * being retrieved. For example, if data can be categorized as "live" vs "saved" - * then this field can be used to provide an indication of "saved" vs "live" data. - * Not all structured data supports subtypes and if they are supported then the - * structured data will specify the valid values. If structured data is requested - * that supports subtypes but no subtype is given then it is implementation specific - * what will be returned. Some structure data can support a subtype of "All" which - * would cause a list of structures to be returned for all supported subtypes. "All" - * is only used on the hwrm_get_structured_data command. + * Subtype is an optional field used to specify additional information + * of the data being retrieved. For example, if data can be categorized + * as "live" vs "saved" then this field can be used to provide an + * indication of "saved" vs "live" data. Not all structured data + * supports subtypes and if they are supported then the structured data + * will specify the valid values. If structured data is requested that + * supports subtypes but no subtype is given then it is implementation + * specific what will be returned. Some structure data can support a + * subtype of "All" which would cause a list of structures to be + * returned for all supported subtypes. "All" is only used on the + * hwrm_get_structured_data command. */ uint16_t subtype; #define HWRM_FW_GET_STRUCTURED_DATA_INPUT_SUBTYPE_UNUSED UINT32_C(0x0) @@ -56237,7 +62046,7 @@ typedef struct hwrm_fw_get_structured_data_input { #define HWRM_FW_GET_STRUCTURED_DATA_INPUT_SUBTYPE_NON_TPMR_OPERATIONAL UINT32_C(0x202) #define HWRM_FW_GET_STRUCTURED_DATA_INPUT_SUBTYPE_HOST_OPERATIONAL UINT32_C(0x300) #define HWRM_FW_GET_STRUCTURED_DATA_INPUT_SUBTYPE_LAST HWRM_FW_GET_STRUCTURED_DATA_INPUT_SUBTYPE_HOST_OPERATIONAL - /* Number of elements. This allows support of arrayed data */ + /* Number of elements. This allows support of arrayed data */ uint8_t count; uint8_t unused_0; } hwrm_fw_get_structured_data_input_t, *phwrm_fw_get_structured_data_input_t; @@ -56261,9 +62070,9 @@ typedef struct hwrm_fw_get_structured_data_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56345,10 +62154,12 @@ typedef struct hwrm_fw_ipc_msg_input { /* Command ID */ uint16_t command_id; /* RoCE LAG message */ - #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_ROCE_LAG UINT32_C(0x1) + #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_ROCE_LAG UINT32_C(0x1) /* Query information on PF mapping for x86 and MAIA. */ - #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_MHB_HOST UINT32_C(0x2) - #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_LAST HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_MHB_HOST + #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_MHB_HOST UINT32_C(0x2) + /* RoCE driver version details to be sent to chimp */ + #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_ROCE_DRVR_VERSION UINT32_C(0x3) + #define HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_LAST HWRM_FW_IPC_MSG_INPUT_COMMAND_ID_ROCE_DRVR_VERSION /* Source processor for this command. */ uint8_t src_processor; /* Chimp processor */ @@ -56387,9 +62198,9 @@ typedef struct hwrm_fw_ipc_msg_output { uint8_t reserved48[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56459,9 +62270,9 @@ typedef struct hwrm_fw_ipc_mailbox_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56549,9 +62360,9 @@ typedef struct hwrm_fw_ecn_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56612,9 +62423,9 @@ typedef struct hwrm_fw_ecn_qcfg_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56737,12 +62548,42 @@ typedef struct hwrm_fw_health_check_output { * or '1' if they do not match. */ #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_FRU_MISMATCH UINT32_C(0x1000) + /* + * This bit is '0' if the primary CRT2 was used this boot, + * or '1' if the secondary CRT2 was used. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_CRT2_BOOTED UINT32_C(0x2000) + /* + * This bit is '0' if the primary and secondary CRT2 images + * match, or '1' if they do not match. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_CRT2_MISMATCH UINT32_C(0x4000) + /* + * This bit is '0' if the primary GXRT was used this boot, + * or '1' if the secondary GXRT was used. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_GXRT_BOOTED UINT32_C(0x8000) + /* + * This bit is '0' if the primary and secondary GXRT images + * match, or '1' if they do not match. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_GXRT_MISMATCH UINT32_C(0x10000) + /* + * This bit is '0' if the primary SRT2 was used this boot, + * or '1' if the secondary SRT2 was used. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_SRT2_BOOTED UINT32_C(0x20000) + /* + * This bit is '0' if the primary and secondary SRT2 images + * match, or '1' if they do not match. + */ + #define HWRM_FW_HEALTH_CHECK_OUTPUT_FW_STATUS_SRT2_MISMATCH UINT32_C(0x40000) uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56807,12 +62648,12 @@ typedef struct hwrm_fw_livepatch_query_output { uint16_t resp_len; /* * This field represents the patch version string of the NVM installed - * livepatch. (ASCII chars with NULL at the end). + * livepatch. (ASCII chars with NULL at the end). */ char install_ver[32]; /* * This field represents the patch version string of the active - * livepatch. (ASCII chars with NULL at the end). + * livepatch. (ASCII chars with NULL at the end). */ char active_ver[32]; uint16_t status_flags; @@ -56823,9 +62664,9 @@ typedef struct hwrm_fw_livepatch_query_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56871,7 +62712,7 @@ typedef struct hwrm_fw_livepatch_input { uint8_t opcode; /* * Activate a livepatch that is NVM installed or via direct load - * from host memory. Activate will authenticate a signed patch, + * from host memory. Activate will authenticate a signed patch, * verify the patch version for compatibility and apply the * livepatch to existing firmware at run-time. */ @@ -56894,7 +62735,7 @@ typedef struct hwrm_fw_livepatch_input { /* Load a livepatch currently installed on NVM. */ #define HWRM_FW_LIVEPATCH_INPUT_LOADTYPE_NVM_INSTALL UINT32_C(0x1) /* - * Load a livepatch directly from host memory. The livepatch image + * Load a livepatch directly from host memory. The livepatch image * is available at host_addr. */ #define HWRM_FW_LIVEPATCH_INPUT_LOADTYPE_MEMORY_DIRECT UINT32_C(0x2) @@ -56921,9 +62762,9 @@ typedef struct hwrm_fw_livepatch_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -56947,16 +62788,16 @@ typedef struct hwrm_fw_livepatch_cmd_err { #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_NOT_SUPPORTED UINT32_C(0x3) /* Livepatch image is not installed in NVRAM. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_NOT_INSTALLED UINT32_C(0x4) - /* Deactivate failed. Firmware is not currently patched. */ + /* Deactivate failed. Firmware is not currently patched. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_NOT_PATCHED UINT32_C(0x5) /* Authentication of a signed livepatch failed. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_AUTH_FAIL UINT32_C(0x6) - /* Livepatch header check failed. Patch incompatible. */ + /* Livepatch header check failed. Patch incompatible. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_INVALID_HEADER UINT32_C(0x7) /* Livepatch size incompatible. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_INVALID_SIZE UINT32_C(0x8) /* - * Activate failed. Firmware has already been patched. Deactivate + * Activate failed. Firmware has already been patched. Deactivate * existing livepatch before proceeding. */ #define HWRM_FW_LIVEPATCH_CMD_ERR_CODE_ALREADY_PATCHED UINT32_C(0x9) @@ -57047,11 +62888,32 @@ typedef struct hwrm_fw_sync_input { */ #define HWRM_FW_SYNC_INPUT_SYNC_ACTION_SYNC_FRU UINT32_C(0x40) /* + * If action is '1' (sync) and this bit is set, the CRT2 + * images will be synchronized, copying from the instance + * used for boot to the other instance, if they currently + * do not match. + */ + #define HWRM_FW_SYNC_INPUT_SYNC_ACTION_SYNC_CRT2 UINT32_C(0x80) + /* + * If action is '1' (sync) and this bit is set, the GXRT + * images will be synchronized, copying from the instance + * used for boot to the other instance, if they currently + * do not match. + */ + #define HWRM_FW_SYNC_INPUT_SYNC_ACTION_SYNC_GXRT UINT32_C(0x100) + /* + * If action is '1' (sync) and this bit is set, the SRT2 + * images will be synchronized, copying from the instance + * used for boot to the other instance, if they currently + * do not match. + */ + #define HWRM_FW_SYNC_INPUT_SYNC_ACTION_SYNC_SRT2 UINT32_C(0x200) + /* * A value of '1' instructs the firmware to perform an image * synchronization of the firmware types denoted by the - * sync_sbi, sync_srt, sync_crt bits. A value of '0' just - * requests the status for the previously requested sync - * operation. + * sync_sbi, sync_srt, sync_crt, sync_crt2, sync_srt2 bits. + * A value of '0' just requests the status for the previously + * requested sync operation. */ #define HWRM_FW_SYNC_INPUT_SYNC_ACTION_ACTION UINT32_C(0x80000000) uint8_t unused_0[4]; @@ -57085,7 +62947,7 @@ typedef struct hwrm_fw_sync_output { #define HWRM_FW_SYNC_OUTPUT_SYNC_STATUS_ERR_CODE_GENERAL UINT32_C(0x3) #define HWRM_FW_SYNC_OUTPUT_SYNC_STATUS_ERR_CODE_LAST HWRM_FW_SYNC_OUTPUT_SYNC_STATUS_ERR_CODE_GENERAL /* - * This bit is '1' if the syncronization request has completed + * This bit is '1' if the synchronization request has completed * with an error; the 'err_code' field can be used to obtain * information about error type. */ @@ -57093,7 +62955,7 @@ typedef struct hwrm_fw_sync_output { /* * This bit is '0' if the previously requested synchronization * command is still in progress, or '1' if the previously - * requested sync command has completed. If '1', the 'sync_err' + * requested sync command has completed. If '1', the 'sync_err' * field will indicate if it completed successfully or with * an error. */ @@ -57101,9 +62963,9 @@ typedef struct hwrm_fw_sync_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57160,7 +63022,7 @@ typedef struct hwrm_fw_state_qcaps_output { uint16_t resp_len; /* * This field indicates the size in bytes required by host backup - * memory. Host software should allocate memory according to this + * memory. Host software should allocate memory according to this * size requirement and pass the allocated memory to the * HWRM_FW_STATE_BACKUP and HWRM_FW_STATE_RESTORE commands in the form * of PBL data as specified in those commands. @@ -57193,7 +63055,7 @@ typedef struct hwrm_fw_state_qcaps_output { uint32_t fw_status_blackout; /* * This field indicates a max time for firmware to poll for status - * 0x8000 before assuming a reset failure occurred. This time does + * 0x8000 before assuming a reset failure occurred. This time does * not include fw_status_blackout time which would immediately precede * this wait. */ @@ -57202,9 +63064,9 @@ typedef struct hwrm_fw_state_qcaps_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57350,9 +63212,9 @@ typedef struct hwrm_fw_state_unquiesce_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57459,7 +63321,7 @@ typedef struct hwrm_fw_state_backup_output { * This bit is '0' if the backout was done in a way that firmware * may continue running normally after the backup, for example if * the host elects to skip the subsequent reset and restore for any - * reason. A value of '1' indicates the act of backing up has left + * reason. A value of '1' indicates the act of backing up has left * the firmware/device in a state where subsequent reset is * required, for example of probing state of a queue leaves changes * state in a way that is detectable by users. @@ -57471,9 +63333,9 @@ typedef struct hwrm_fw_state_backup_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57581,7 +63443,7 @@ typedef struct hwrm_fw_state_restore_output { /* * If a failure occurs (complete is 0), restore attempts to * completely roll back any state applied so that the failure - * results in no state change. This flag indicates whether that + * results in no state change. This flag indicates whether that * rollback completed successfully and thoroughly. */ #define HWRM_FW_STATE_RESTORE_OUTPUT_RESTORE_STATUS_FAILURE_ROLLBACK_COMPLETED UINT32_C(0x40000000) @@ -57590,9 +63452,9 @@ typedef struct hwrm_fw_state_restore_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57717,7 +63579,7 @@ typedef struct hwrm_fw_secure_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -57794,9 +63656,9 @@ typedef struct hwrm_exec_fwd_resp_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57870,9 +63732,9 @@ typedef struct hwrm_reject_fwd_resp_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -57924,7 +63786,7 @@ typedef struct hwrm_fwd_resp_input { uint16_t encap_resp_target_id; /* * This value indicates the completion ring the encapsulated - * response will be optionally completed on. If the value is + * response will be optionally completed on. If the value is * -1, then no CR completion shall be generated for the * encapsulated response. Any other value must be a * valid CR ring_id value. If a valid encap_resp_cmpl_ring @@ -57961,9 +63823,9 @@ typedef struct hwrm_fwd_resp_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58033,9 +63895,9 @@ typedef struct hwrm_fwd_async_event_cmpl_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58079,7 +63941,7 @@ typedef struct hwrm_temp_monitor_query_input { uint64_t resp_addr; } hwrm_temp_monitor_query_input_t, *phwrm_temp_monitor_query_input_t; -/* hwrm_temp_monitor_query_output (size:128b/16B) */ +/* hwrm_temp_monitor_query_output (size:192b/24B) */ typedef struct hwrm_temp_monitor_query_output { /* The specific error status for the command. */ @@ -58131,6 +63993,11 @@ typedef struct hwrm_temp_monitor_query_output { */ #define HWRM_TEMP_MONITOR_QUERY_OUTPUT_FLAGS_EXT_TEMP_FIELDS_AVAILABLE UINT32_C(0x10) /* + * "1" in this bit indicates the thermal threshold values are + * available. + */ + #define HWRM_TEMP_MONITOR_QUERY_OUTPUT_FLAGS_THRESHOLD_VALUES_AVAILABLE UINT32_C(0x20) + /* * This field encodes the current device temperature in Celsius. * This field is unsigned and the value range of 0 to 255 is used to * indicate a temperature range from -64 to +191. The actual @@ -58158,10 +64025,33 @@ typedef struct hwrm_temp_monitor_query_output { */ uint8_t om_temp2; /* + * This field reports the device's threshold value for reporting + * a warning indication. The temperature is reported in Celsius. + */ + uint8_t warn_threshold; + /* + * This field reports the device's threshold value for reporting + * a critical indication. The temperature is reported in Celsius. + */ + uint8_t critical_threshold; + /* + * This field reports the device's threshold value for reporting + * a fatal indication. The temperature is reported in Celsius. + */ + uint8_t fatal_threshold; + /* + * This field reports the threshold value at which the device will + * a perform a self shutdown. The temperature is reported in Celsius. + * If the value is zero, then that indicates self shutdown is not + * configured. + */ + uint8_t shutdown_threshold; + uint8_t unused_0[4]; + /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58235,9 +64125,9 @@ typedef struct hwrm_reg_power_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58297,9 +64187,9 @@ typedef struct hwrm_core_frequency_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58413,9 +64303,9 @@ typedef struct hwrm_reg_power_histogram_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58625,9 +64515,9 @@ typedef struct hwrm_wol_filter_alloc_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58708,9 +64598,9 @@ typedef struct hwrm_wol_filter_free_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58869,9 +64759,9 @@ typedef struct hwrm_wol_filter_qcfg_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -58963,9 +64853,9 @@ typedef struct hwrm_wol_reason_qcfg_output { uint8_t unused_0[4]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59009,7 +64899,7 @@ typedef struct hwrm_dbg_read_direct_input { uint64_t resp_addr; /* * host address where the data content will be written - * when the request is complete. This area must be 16B aligned. + * when the request is complete. This area must be 16B aligned. */ uint64_t host_dest_addr; /* address(in ChiMP view) to start reading */ @@ -59038,9 +64928,9 @@ typedef struct hwrm_dbg_read_direct_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59104,9 +64994,9 @@ typedef struct hwrm_dbg_write_direct_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59150,7 +65040,7 @@ typedef struct hwrm_dbg_read_indirect_input { uint64_t resp_addr; /* * host address where the data content will be written - * when the request is complete. This area must be 16B aligned. + * when the request is complete. This area must be 16B aligned. */ uint64_t host_dest_addr; /* Length of host buffer used for transferring debug data. */ @@ -59241,9 +65131,9 @@ typedef struct hwrm_dbg_read_indirect_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59362,9 +65252,9 @@ typedef struct hwrm_dbg_write_indirect_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59450,9 +65340,9 @@ typedef struct hwrm_dbg_dump_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59496,7 +65386,15 @@ typedef struct hwrm_dbg_erase_nvm_input { uint64_t resp_addr; uint16_t flags; /* If set to 1, then erase all locations in persistent storage. */ - #define HWRM_DBG_ERASE_NVM_INPUT_FLAGS_ERASE_ALL UINT32_C(0x1) + #define HWRM_DBG_ERASE_NVM_INPUT_FLAGS_ERASE_ALL UINT32_C(0x1) + /* + * This bit is only used when external secure SoC is used for + * Secure boot. This bit is utilized to differentiate between + * erase for NIC or Security SoC non-volatile storage on the + * device. If this bit is set, then erases all locations in the + * persistent storage of the secure SoC non-volatile storage device. + */ + #define HWRM_DBG_ERASE_NVM_INPUT_FLAGS_SECURITY_SOC_NVM UINT32_C(0x2) uint8_t unused_0[6]; } hwrm_dbg_erase_nvm_input_t, *phwrm_dbg_erase_nvm_input_t; @@ -59514,9 +65412,9 @@ typedef struct hwrm_dbg_erase_nvm_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59588,7 +65486,7 @@ typedef struct hwrm_dbg_cfg_input { /* * If set to 1, firmware is allowed to be unresponsive to heartbeat * health checks, allowing for JTAG debugging scenarios where the - * debugger has the firmware processes stopped indefinitely. This + * debugger has the firmware processes stopped indefinitely. This * flag has effect only on debug builds of firmware. */ #define HWRM_DBG_CFG_INPUT_FLAGS_JTAG_DEBUG UINT32_C(0x20) @@ -59615,9 +65513,9 @@ typedef struct hwrm_dbg_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59760,9 +65658,9 @@ typedef struct hwrm_dbg_crashdump_header_output { uint8_t unused_2[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59838,9 +65736,9 @@ typedef struct hwrm_dbg_crashdump_erase_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -59903,7 +65801,7 @@ typedef struct hwrm_dbg_qcaps_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * FID value. This value is used to identify operations on the PCI + * FID value. This value is used to identify operations on the PCI * bus as belonging to a particular PCI function. */ uint16_t fid; @@ -59920,19 +65818,39 @@ typedef struct hwrm_dbg_qcaps_output { #define HWRM_DBG_QCAPS_OUTPUT_COREDUMP_COMPONENT_DISABLE_CAPS_NVRAM UINT32_C(0x1) uint32_t flags; /* If 1, FW supports writing a crashdump to NVM. */ - #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_CRASHDUMP_NVM UINT32_C(0x1) + #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_CRASHDUMP_NVM UINT32_C(0x1) /* If 1, FW supports writing a crashdump to host ddr. */ #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_CRASHDUMP_HOST_DDR UINT32_C(0x2) /* If 1, FW supports writing a crashdump to soc ddr. */ #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_CRASHDUMP_SOC_DDR UINT32_C(0x4) /* If 1, FW supports USEQ operations */ - #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_USEQ UINT32_C(0x8) + #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_USEQ UINT32_C(0x8) + /* + * If 1, FW supports writing a coredump to host ddr. + * The driver instance can allocate the Host memory to + * capture coredump. + */ + #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_COREDUMP_HOST_DDR UINT32_C(0x10) + /* + * If 1, FW supports HWRM_DBG_COREDUMP_CAPTURE command to collect the + * coredump into the Host memory address. The driver instance can + * invoke the command to collect coredump upon any fatal event. + * Tx timeout is an example scenario. + */ + #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_COREDUMP_HOST_CAPTURE UINT32_C(0x20) + /* + * If 1, FW supports the PTrace capability.PTrace(PEX Trace Capture) + * provides a means for capturing and buffering PCIe TLPs, DLLPs and + * ordered sets following in both directions through a PEX station. + * This capability is advertised only on PF's. + */ + #define HWRM_DBG_QCAPS_OUTPUT_FLAGS_PTRACE UINT32_C(0x40) uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60018,13 +65936,13 @@ typedef struct hwrm_dbg_qcfg_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* - * FID value. This value is used to identify operations on the PCI + * FID value. This value is used to identify operations on the PCI * bus as belonging to a particular PCI function. */ uint16_t fid; uint8_t unused_0[2]; /* - * Size in bytes of a coredump file created by the FW. This takes into + * Size in bytes of a coredump file created by the FW. This takes into * consideration any components selected in the * coredump_component_disable_flags field from hwrm_dbg_qcfg_input. */ @@ -60046,7 +65964,7 @@ typedef struct hwrm_dbg_qcfg_output { */ #define HWRM_DBG_QCFG_OUTPUT_FLAGS_FW_TRACE UINT32_C(0x4) /* - * If set to 1, then completion ring logging is enabled for the + * If set to 1, then completion ring logging is enabled for the * secondary firmware. Disabled otherwise. */ #define HWRM_DBG_QCFG_OUTPUT_FLAGS_FW_TRACE_SECONDARY UINT32_C(0x8) @@ -60058,7 +65976,7 @@ typedef struct hwrm_dbg_qcfg_output { /* * If set to 1, firmware is allowed to be unresponsive to heartbeat * health checks, allowing for JTAG debugging scenarios where the - * debugger has the firmware processes stopped indefinitely. This + * debugger has the firmware processes stopped indefinitely. This * flag has effect only on debug builds of firmware. */ #define HWRM_DBG_QCFG_OUTPUT_FLAGS_JTAG_DEBUG UINT32_C(0x20) @@ -60070,16 +65988,16 @@ typedef struct hwrm_dbg_qcfg_output { uint16_t async_cmpl_ring; uint8_t unused_2[2]; /* - * Size in bytes of a crashdump file created by the FW. Uses input + * Size in bytes of a crashdump file created by the FW. Uses input * flags to determine medium destination and corresponding size. */ uint32_t crashdump_size; uint8_t unused_3[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60188,9 +66106,9 @@ typedef struct hwrm_dbg_crashdump_medium_cfg_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60267,7 +66185,7 @@ typedef struct hwrm_dbg_coredump_list_input { uint64_t resp_addr; /* * host address where the data content will be written - * when the request is complete. This area must be 16B aligned. + * when the request is complete. This area must be 16B aligned. */ uint64_t host_dest_addr; /* Length of host buffer used for transferring debug data. */ @@ -60309,9 +66227,9 @@ typedef struct hwrm_dbg_coredump_list_output { uint8_t unused_1; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60364,8 +66282,18 @@ typedef struct hwrm_dbg_coredump_initiate_input { /* * bit 0: live data * bit 1: crashed data + * bit 2: collect context l1 cache */ uint8_t seg_flags; + /* Not Used. */ + #define HWRM_DBG_COREDUMP_INITIATE_INPUT_SEG_FLAGS_LIVE_DATA UINT32_C(0x1) + /* Not Used. */ + #define HWRM_DBG_COREDUMP_INITIATE_INPUT_SEG_FLAGS_CRASH_DATA UINT32_C(0x2) + /* + * If this bit is set, this setting will enforce firmware to collect + * CFCx l1 cache. + */ + #define HWRM_DBG_COREDUMP_INITIATE_INPUT_SEG_FLAGS_COLLECT_CTX_L1_CACHE UINT32_C(0x4) /* Not used. */ uint8_t unused_1[7]; } hwrm_dbg_coredump_initiate_input_t, *phwrm_dbg_coredump_initiate_input_t; @@ -60384,9 +66312,9 @@ typedef struct hwrm_dbg_coredump_initiate_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60452,7 +66380,7 @@ typedef struct hwrm_dbg_coredump_retrieve_input { uint64_t resp_addr; /* * host address where the data content will be written - * when the request is complete. This area must be 16B aligned. + * when the request is complete. This area must be 16B aligned. */ uint64_t host_dest_addr; /* Length of host buffer used for transferring debug data. */ @@ -60504,9 +66432,9 @@ typedef struct hwrm_dbg_coredump_retrieve_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60550,13 +66478,14 @@ typedef struct hwrm_dbg_i2c_cmd_input { uint64_t resp_addr; /* * host address where the data content will be read or written. - * For master write, data content will be read from host memory and write - * to i2c slave. (size defined by write_size) - * For master read, data content will be read from i2c slave and write to - * the host memory. (size defined by read_size) - * For master write/read, data content will be first read from host memory - * and write to i2c slave. (size defined by write_size) then data read from - * i2c slave will be written back to the same host memory. (size defined by read_size) + * For master write, data content will be read from host memory and + * write to i2c slave. (size defined by write_size) + * For master read, data content will be read from i2c slave and write + * to the host memory. (size defined by read_size) + * For master write/read, data content will be first read from host + * memory and write to i2c slave. (size defined by write_size) then + * data read from i2c slave will be written back to the same host + * memory. (size defined by read_size) */ uint64_t host_dest_addr; /* read size in bytes, valid only for master read and write/read */ @@ -60564,7 +66493,8 @@ typedef struct hwrm_dbg_i2c_cmd_input { /* write size in bytes, valid only for master write and write/read */ uint16_t write_size; /* - * instance of i2c channel for this operation. Valid if multiple instances + * instance of i2c channel for this operation. Valid if multiple + * instances * of i2c channels are connected to external i2c devices. */ uint8_t chnl_id; @@ -60607,9 +66537,9 @@ typedef struct hwrm_dbg_i2c_cmd_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60681,9 +66611,9 @@ typedef struct hwrm_dbg_fw_cli_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60761,12 +66691,18 @@ typedef struct hwrm_dbg_ring_info_get_output { * Not valid for other ring types. */ uint32_t cag_vector_ctrl; - uint8_t unused_0[3]; + /* + * Steering Tag. The current value of the steering tag for the ring. + * The steering tag is only valid if it is advertised by Firmware in + * flags_ext2.steering_tag_supported of hwrm_func_qcaps response. + */ + uint16_t st_tag; + uint8_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60845,9 +66781,9 @@ typedef struct hwrm_dbg_drv_trace_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -60889,9 +66825,15 @@ typedef struct hwrm_dbg_useq_alloc_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; - /* Number size of the allocation, in bytes, for the USEQ in the code words array */ + /* + * Number size of the allocation, in bytes, for the USEQ in the code + * words array + */ uint32_t size; - /* Number of bytes executing the USEQ will produce. Must be a multiple of 4 */ + /* + * Number of bytes executing the USEQ will produce. Must be a multiple + * of 4 + */ uint16_t output_bytes; /* This field is reserved */ uint16_t unused_0; @@ -60931,9 +66873,9 @@ typedef struct hwrm_dbg_useq_alloc_output { uint16_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61013,9 +66955,9 @@ typedef struct hwrm_dbg_useq_free_output { uint32_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61100,9 +67042,9 @@ typedef struct hwrm_dbg_useq_flush_output { uint32_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61149,9 +67091,9 @@ typedef struct hwrm_dbg_useq_cw_cfg_input { /* * The code words given in this message will be placed * at this offset from the starting code word for this - * usid. NOTE: when offset is zero, the first 6 32-bit + * usid. NOTE: when offset is zero, the first 6 32-bit * words may contain values for F0-F7 as well as the - * main code word index. This is determined by checking + * main code word index. This is determined by checking * the usid_ctrl_present flag. */ uint16_t offset; @@ -61167,14 +67109,14 @@ typedef struct hwrm_dbg_useq_cw_cfg_input { uint16_t flags; /* * When set, the opaque data begins with a block of control - * information to be associated with the usid. This includes + * information to be associated with the usid. This includes * F0-F7 code word indexes as well as the code word index for * main. */ #define HWRM_DBG_USEQ_CW_CFG_INPUT_FLAGS_USID_CTRL_PRESENT UINT32_C(0x1) /* * When set, opaque contains a 64b host address used to DMA - * the entire code word sequence. The offset within the + * the entire code word sequence. The offset within the * opaque data depends on the state of other flags. */ #define HWRM_DBG_USEQ_CW_CFG_INPUT_FLAGS_USE_DMA UINT32_C(0x2) @@ -61296,9 +67238,9 @@ typedef struct hwrm_dbg_useq_qcaps_output { uint32_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61345,20 +67287,21 @@ typedef struct hwrm_dbg_useq_sched_cfg_input { /* This value will leave the global scheduler in its current state */ #define HWRM_DBG_USEQ_SCHED_CFG_INPUT_NO_CHANGE UINT32_C(0x0) /* - * This value disables the global scheduler. This mode must be used + * This value disables the global scheduler. This mode must be used * when the RUN command is being used to run individual sequences. */ #define HWRM_DBG_USEQ_SCHED_CFG_INPUT_DISABLE UINT32_C(0x1) /* - * This value enables the global scheduler. When enabled, USEQs will + * This value enables the global scheduler. When enabled, USEQs will * be scheduled based on their polling intervals */ #define HWRM_DBG_USEQ_SCHED_CFG_INPUT_ENABLE UINT32_C(0x2) #define HWRM_DBG_USEQ_SCHED_CFG_INPUT_LAST HWRM_DBG_USEQ_SCHED_CFG_INPUT_ENABLE /* - * The given polling interval will be associated with this USID. A value - * of -1 indicates that the USID is invalid. The invalid USID is used when - * using this message only for global scheduler configuration. + * The given polling interval will be associated with this USID. A + * value of -1 indicates that the USID is invalid. The invalid USID is + * used when using this message only for global scheduler + * configuration. */ uint16_t usid; /* This value represents microseconds between runs of the USEQ */ @@ -61397,9 +67340,9 @@ typedef struct hwrm_dbg_useq_sched_cfg_output { uint32_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61448,34 +67391,40 @@ typedef struct hwrm_dbg_useq_run_input { /* This run type will execute the requested USEQ only a single time */ #define HWRM_DBG_USEQ_RUN_INPUT_RUN_TYPE_SINGLE UINT32_C(0x0) /* - * This run type will execute the requested USEQ a number of times given - * by run_cnt with a run interval given by the run_interval parameter. + * This run type will execute the requested USEQ a number of times + * given by run_cnt with a run interval given by the run_interval + * parameter. */ #define HWRM_DBG_USEQ_RUN_INPUT_RUN_TYPE_CNT UINT32_C(0x1) /* - * This run type will execute the requested USEQ as many times as it needs - * to fill an entire buffer to return to the host. The runs will occur - * with a run interval given by the run_interval parameter. + * This run type will execute the requested USEQ as many times as it + * needs to fill an entire buffer to return to the host. The runs + * will occur with a run interval given by the run_interval + * parameter. */ #define HWRM_DBG_USEQ_RUN_INPUT_RUN_TYPE_FILL_BUF UINT32_C(0x2) #define HWRM_DBG_USEQ_RUN_INPUT_RUN_TYPE_LAST HWRM_DBG_USEQ_RUN_INPUT_RUN_TYPE_FILL_BUF /* - * If indicated by flags, this represents the number of times to run the USEQ. - * Note that runs are stopped if the buffer fills prior regardless of the - * number of runs. For example, if a run_cnt of 10 is specified and 3 runs - * results in the buffer being full then only 3 runs are executed. + * If indicated by flags, this represents the number of times to run + * the USEQ. Note that runs are stopped if the buffer fills prior + * regardless of the number of runs. For example, if a run_cnt of 10 is + * specified and 3 runs results in the buffer being full then only 3 + * runs are executed. */ uint8_t run_cnt; /* - * This value represents microseconds between runs of the USEQ when running - * multiple times as indicated by flags. + * This value represents microseconds between runs of the USEQ when + * running multiple times as indicated by flags. */ uint32_t run_interval; - /* Address of the host buffer where collected USEQ output data will be placed */ + /* + * Address of the host buffer where collected USEQ output data will be + * placed + */ uint64_t host_dest_addr; /* - * Size, in bytes, of the memory associated with host_dest_addr. It is expected - * that this is >= 4096 + * Size, in bytes, of the memory associated with host_dest_addr. It is + * expected that this is >= 4096 */ uint32_t host_dest_len; /* This field is reserved */ @@ -61511,16 +67460,16 @@ typedef struct hwrm_dbg_useq_run_output { /* Reserved */ uint8_t useq_resp_unused_0[3]; /* - * The length, in bytes, of the amount of data placed in the corresponding - * host_dest_addr given in the input message. This will always be a multiple - * of 4096 + * The length, in bytes, of the amount of data placed in the + * corresponding host_dest_addr given in the input message. This will + * always be a multiple of 4096 */ uint32_t host_dest_filled_len; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; @@ -61563,14 +67512,15 @@ typedef struct hwrm_dbg_useq_delivery_req_input { */ uint64_t resp_addr; /* - * Eight destination addresses provide host memory space for FW to deliver - * USEQ output details. A value of 0x0 for the address can be used to - * inform FW that the buffer is not available. + * Eight destination addresses provide host memory space for FW to + * deliver USEQ output details. A value of 0x0 for the address can be + * used to inform FW that the buffer is not available. */ uint64_t host_dest_addrs[8]; /* - * The length, in bytes, of the corresponding host_dest_addrs array entry. Each - * valid hist_dest_addrs entry must have a len of at least 4096 bytes + * The length, in bytes, of the corresponding host_dest_addrs array + * entry. Each valid hist_dest_addrs entry must have a len of at least + * 4096 bytes. */ uint32_t host_dest_len[8]; } hwrm_dbg_useq_delivery_req_input_t, *phwrm_dbg_useq_delivery_req_input_t; @@ -61604,29 +67554,578 @@ typedef struct hwrm_dbg_useq_delivery_req_output { /* Reserved */ uint8_t useq_resp_unused_0[3]; /* - * The length, in bytes, of the amount of data placed in the corresponding - * host_dest_addrs entry given in the input message. This will always be a - * multiple of 4096 + * The length, in bytes, of the amount of data placed in the + * corresponding host_dest_addrs entry given in the input message. This + * will always be a multiple of 4096. */ uint32_t host_dest_filled_len[8]; /* This field is reserved */ uint32_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint32_t valid; } hwrm_dbg_useq_delivery_req_output_t, *phwrm_dbg_useq_delivery_req_output_t; +/***************************** + * hwrm_dbg_log_buffer_flush * + *****************************/ + + +/* hwrm_dbg_log_buffer_flush_input (size:192b/24B) */ + +typedef struct hwrm_dbg_log_buffer_flush_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Type of trace buffer to flush. */ + uint16_t type; + /* SRT trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_SRT_TRACE UINT32_C(0x0) + /* SRT2 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_SRT2_TRACE UINT32_C(0x1) + /* CRT trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CRT_TRACE UINT32_C(0x2) + /* CRT2 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CRT2_TRACE UINT32_C(0x3) + /* RIGP0 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_RIGP0_TRACE UINT32_C(0x4) + /* L2 HWRM trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_L2_HWRM_TRACE UINT32_C(0x5) + /* RoCE HWRM trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_ROCE_HWRM_TRACE UINT32_C(0x6) + /* Context Accelerator CPU 0 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CA0_TRACE UINT32_C(0x7) + /* Context Accelerator CPU 1 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CA1_TRACE UINT32_C(0x8) + /* Context Accelerator CPU 2 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CA2_TRACE UINT32_C(0x9) + /* RIGP1 trace. */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_RIGP1_TRACE UINT32_C(0xa) + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_LAST HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_RIGP1_TRACE + uint8_t unused_1[2]; + /* Control flags. */ + uint32_t flags; + /* + * When set, it indicates that all buffers should be flushed. + * The type will be ignored. + */ + #define HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_FLAGS_FLUSH_ALL_BUFFERS UINT32_C(0x1) +} hwrm_dbg_log_buffer_flush_input_t, *phwrm_dbg_log_buffer_flush_input_t; + +/* hwrm_dbg_log_buffer_flush_output (size:128b/16B) */ + +typedef struct hwrm_dbg_log_buffer_flush_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * Specifies the current host buffer offset. Data up to this offset + * has been populated by the firmware. For example, if the firmware + * has DMA-ed 8192 bytes to the host buffer, then this field has a + * value of 8192. This field rolls over to zero once the firmware + * writes the last page of the host buffer + */ + uint32_t current_buffer_offset; + uint8_t unused_1[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_dbg_log_buffer_flush_output_t, *phwrm_dbg_log_buffer_flush_output_t; + +/************************ + * hwrm_dbg_serdes_test * + ************************/ + + +/* hwrm_dbg_serdes_test_input (size:320b/40B) */ + +typedef struct hwrm_dbg_serdes_test_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* Host address data is to DMA'd to. */ + uint64_t resp_data_addr; + /* + * This field contains the offset into the captured data to begin + * copying the data to the host from. This should be set to 0 on the + * initial call to this command. + */ + uint32_t resp_data_offset; + /* + * Size of the buffer pointed to by resp_data_addr. The firmware may + * use this entire buffer or less than the entire buffer, but never + * more. + */ + uint16_t data_len; + /* + * This field allows this command to request the individual serdes + * tests to be run using this command. + */ + uint8_t flags; + /* Unused. */ + #define HWRM_DBG_SERDES_TEST_INPUT_FLAGS_UNUSED_TEST_MASK UINT32_C(0x7) + #define HWRM_DBG_SERDES_TEST_INPUT_FLAGS_UNUSED_TEST_SFT 0 + /* Display eye_projection */ + #define HWRM_DBG_SERDES_TEST_INPUT_FLAGS_EYE_PROJECTION UINT32_C(0x8) + /* Run the PCIe serdes test. */ + #define HWRM_DBG_SERDES_TEST_INPUT_FLAGS_PCIE_SERDES_TEST UINT32_C(0x10) + /* Run the Ethernet serdes test. */ + #define HWRM_DBG_SERDES_TEST_INPUT_FLAGS_ETHERNET_SERDES_TEST UINT32_C(0x20) + uint8_t options; + /* + * This field represents the lane number on which tools wants to + * retrieve eye plot. This field is valid only when pcie_serdes_test + * or ethernet_serdes_test flag is set. For pcie_serdes_test, the + * maximum value is the device pcie lane width minus 1. For + * ethernet_serdes_test, the maximum value is the total lanes of + * the network port minus 1. Valid values from 0 to 16. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_LANE_NO_MASK UINT32_C(0xf) + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_LANE_NO_SFT 0 + /* This value indicates the Horizontal or vertical plot direction. */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_DIRECTION UINT32_C(0x10) + /* Value 0 indicates Horizontal plot request. */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_DIRECTION_HORIZONTAL (UINT32_C(0x0) << 4) + /* Value 1 indicates vertical plot request. */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_DIRECTION_VERTICAL (UINT32_C(0x1) << 4) + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_DIRECTION_LAST HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_DIRECTION_VERTICAL + /* This value indicates eye projection type */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_PROJ_TYPE UINT32_C(0x20) + /* + * Value 0 indicates left/top projection in horizontal/vertical + * This value is valid only when eye_projection flag was set. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_PROJ_TYPE_LEFT_TOP (UINT32_C(0x0) << 5) + /* + * Value 1 indicates right/bottom projection in + * horizontal/vertical. This value is valid only when + * eye_projection flag was set. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_PROJ_TYPE_RIGHT_BOTTOM (UINT32_C(0x1) << 5) + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_PROJ_TYPE_LAST HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_PROJ_TYPE_RIGHT_BOTTOM + /* Reserved for future. */ + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_RSVD_MASK UINT32_C(0xc0) + #define HWRM_DBG_SERDES_TEST_INPUT_OPTIONS_RSVD_SFT 6 + /* + * This field allows this command to request a specific targetBER + * to be run using this command. + */ + uint8_t targetBER; + /* When collecting an eyescope, measure with a target BER of 1e-8 */ + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E8 UINT32_C(0x0) + /* When collecting an eyescope, measure with a target BER of 1e-9 */ + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E9 UINT32_C(0x1) + /* When collecting an eyescope, measure with a target BER of 1e-10 */ + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E10 UINT32_C(0x2) + /* When collecting an eyescope, measure with a target BER of 1e-11 */ + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E11 UINT32_C(0x3) + /* When collecting an eyescope, measure with a target BER of 1e-12 */ + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E12 UINT32_C(0x4) + #define HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_LAST HWRM_DBG_SERDES_TEST_INPUT_TARGETBER_BER_1E12 + /* + * This field allows this command to specify the action to take when + * collecting an eyescope. + */ + uint8_t action; + /* + * Value 0 indicates that collection of the eyescope should be + * returned synchronously in the output. This only applies to + * a targetBER of 1e-8. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_ACTION_SYNCHRONOUS UINT32_C(0x0) + /* + * Value 1 indicates to the firmware to start the collection of the + * eyescope. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_ACTION_START UINT32_C(0x1) + /* + * Value 2 indicates to the firmware to respond with a progress + * percentage of the current eyescope collection from 0.0 to 100.0. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_ACTION_PROGRESS UINT32_C(0x2) + /* + * Value 3 indicates to stop the eyescope. if the progress + * percentage is 100.0, the data will be DMAed back to + * resp_data_addr. + */ + #define HWRM_DBG_SERDES_TEST_INPUT_ACTION_STOP UINT32_C(0x3) + #define HWRM_DBG_SERDES_TEST_INPUT_ACTION_LAST HWRM_DBG_SERDES_TEST_INPUT_ACTION_STOP + uint8_t unused[6]; +} hwrm_dbg_serdes_test_input_t, *phwrm_dbg_serdes_test_input_t; + +/* hwrm_dbg_serdes_test_output (size:192b/24B) */ + +typedef struct hwrm_dbg_serdes_test_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Total length of stored data. */ + uint16_t total_data_len; + /* + * Amount of data DMA'd to host by this call. The driver can use this + * field along with the total_data_len field above to determine the + * value to write to the resp_data_offset field in the next call + * if more than one call to these commands is required to retrieve all + * the stored data. + */ + uint16_t copied_data_len; + /* + * Percentage of completion of collection of BER values from the + * current eyescope operation in tenths of a percentage. 0 (0.0) to + * 1000 (100.0). + */ + uint16_t progress_percent; + /* Timeout in seconds for timeout of an individual BER point. */ + uint16_t timeout; + uint8_t flags; + /* + * This value indicates the structure of data returned by the + * firmware when DMA'ed to resp_data_addr. + */ + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_BIT_COUNT_TYPE UINT32_C(0x1) + /* + * Value 0 indicates that bit_count value is a raw total + * such that BER = error_count / bit_count. + */ + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_BIT_COUNT_TYPE_BIT_COUNT_TOTAL UINT32_C(0x0) + /* + * Value 1 indicates that bit count is a power of + * 2 that bit_count is normalized to. A Value of 42 indicates + * that BER = error_count / 2^42 + */ + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_BIT_COUNT_TYPE_BIT_COUNT_POW2 UINT32_C(0x1) + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_BIT_COUNT_TYPE_LAST HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_BIT_COUNT_TYPE_BIT_COUNT_POW2 + /* Reserved for future. */ + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_RSVD_MASK UINT32_C(0xfe) + #define HWRM_DBG_SERDES_TEST_OUTPUT_FLAGS_RSVD_SFT 1 + uint8_t unused_0; + /* + * Size of header prepended to the bit_count and error_count array. + * Use this value to skip forward to the bit_count and error_count + * array. + */ + uint16_t hdr_size; + uint8_t unused_1[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_dbg_serdes_test_output_t, *phwrm_dbg_serdes_test_output_t; + +/***************************** + * hwrm_dbg_coredump_capture * + *****************************/ + + +/* hwrm_dbg_coredump_capture_input (size:128b/16B) */ + +typedef struct hwrm_dbg_coredump_capture_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_dbg_coredump_capture_input_t, *phwrm_dbg_coredump_capture_input_t; + +/* hwrm_dbg_coredump_capture_output (size:128b/16B) */ + +typedef struct hwrm_dbg_coredump_capture_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_dbg_coredump_capture_output_t, *phwrm_dbg_coredump_capture_output_t; + +/**************************** + * hwrm_dbg_sim_cable_state * + ****************************/ + + +/* hwrm_dbg_sim_cable_state_input (size:192b/24B) */ + +typedef struct hwrm_dbg_sim_cable_state_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* This field allows this command to specify the action to take. */ + uint8_t action; + /* Value 0 indicates to the firmware to insert the cable. */ + #define HWRM_DBG_SIM_CABLE_STATE_INPUT_ACTION_INSERT UINT32_C(0x0) + /* Value 1 indicates to the firmware to remove the cable. */ + #define HWRM_DBG_SIM_CABLE_STATE_INPUT_ACTION_REMOVE UINT32_C(0x1) + #define HWRM_DBG_SIM_CABLE_STATE_INPUT_ACTION_LAST HWRM_DBG_SIM_CABLE_STATE_INPUT_ACTION_REMOVE + uint8_t unused_0[7]; +} hwrm_dbg_sim_cable_state_input_t, *phwrm_dbg_sim_cable_state_input_t; + +/* hwrm_dbg_sim_cable_state_output (size:128b/16B) */ + +typedef struct hwrm_dbg_sim_cable_state_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_dbg_sim_cable_state_output_t, *phwrm_dbg_sim_cable_state_output_t; + +/******************* + * hwrm_dbg_ptrace * + *******************/ + + +/* hwrm_dbg_ptrace_input (size:320b/40B) */ + +typedef struct hwrm_dbg_ptrace_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * Physical address pointer pointing to a host buffer that the PDI + * command's input request. This can be either a host physical address + * (HPA) or a guest physical address (GPA) and must point to a + * physically contiguous block of memory. + */ + uint64_t pdi_cmd_buf_addr; + /* + * Physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t pdi_resp_buf_addr; + /* Host PDI request buffer length. */ + uint32_t pdi_req_buf_len; + uint16_t seq_no; + uint16_t flags; + /* + * when this flag is set, register access will be enabled for the + * ICAP Tx/Egress block. + */ + #define HWRM_DBG_PTRACE_INPUT_FLAGS_SELECT_IN UINT32_C(0x1) + /* + * when this flag is set, register access will be enabled for the + * ICAP Rx/Ingress block. + */ + #define HWRM_DBG_PTRACE_INPUT_FLAGS_SELECT_OUT UINT32_C(0x2) + /* + * when this flag is set, capture will be started for both Tx and + * Rx directions simultaneously. + */ + #define HWRM_DBG_PTRACE_INPUT_FLAGS_GLOBAL_START UINT32_C(0x4) + /* + * when this flag is set, capture will be stopped for both Tx and + * Rx directions simultaneously. + */ + #define HWRM_DBG_PTRACE_INPUT_FLAGS_GLOBAL_STOP UINT32_C(0x8) +} hwrm_dbg_ptrace_input_t, *phwrm_dbg_ptrace_input_t; + +/* hwrm_dbg_ptrace_output (size:128b/16B) */ + +typedef struct hwrm_dbg_ptrace_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint16_t flags; + /* + * When this flag is set, it indicates that there is more data + * available. + * Issue the request again with the next sequence number. + */ + #define HWRM_DBG_PTRACE_OUTPUT_FLAGS_MORE UINT32_C(0x1) + uint16_t data_len; + uint8_t unused_0[3]; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing + * a command completion or response to an internal processor, the order + * of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_dbg_ptrace_output_t, *phwrm_dbg_ptrace_output_t; + /************************** * hwrm_nvm_raw_write_blk * **************************/ -/* hwrm_nvm_raw_write_blk_input (size:256b/32B) */ +/* hwrm_nvm_raw_write_blk_input (size:320b/40B) */ typedef struct hwrm_nvm_raw_write_blk_input { /* The HWRM command request type. */ @@ -61664,11 +68163,22 @@ typedef struct hwrm_nvm_raw_write_blk_input { uint64_t host_src_addr; /* * 32-bit Destination Address. - * This is the NVRAM byte-offset where the source data will be written to. + * This is the NVRAM byte-offset where the source data will be written + * to. */ uint32_t dest_addr; /* Length of data to be written, in bytes. */ uint32_t len; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used for + * secure boot. This bit is utilized to differentiate between + * writes for NIC or Security SoC non-volatile storage on the + * device. If this bit is set, then this write is for the + * Security SoC non-volatile storage on the device. + */ + #define HWRM_NVM_RAW_WRITE_BLK_INPUT_FLAGS_SECURITY_SOC_NVM UINT32_C(0x1) + uint8_t unused_0[7]; } hwrm_nvm_raw_write_blk_input_t, *phwrm_nvm_raw_write_blk_input_t; /* hwrm_nvm_raw_write_blk_output (size:128b/16B) */ @@ -61685,9 +68195,9 @@ typedef struct hwrm_nvm_raw_write_blk_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -61758,9 +68268,9 @@ typedef struct hwrm_nvm_read_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -61771,7 +68281,7 @@ typedef struct hwrm_nvm_read_output { *********************/ -/* hwrm_nvm_raw_dump_input (size:256b/32B) */ +/* hwrm_nvm_raw_dump_input (size:320b/40B) */ typedef struct hwrm_nvm_raw_dump_input { /* The HWRM command request type. */ @@ -61811,6 +68321,16 @@ typedef struct hwrm_nvm_raw_dump_input { uint32_t offset; /* Total length of NVRAM contents to be read, in bytes. */ uint32_t len; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used for + * secure boot. This bit is utilized to differentiate between + * read for NIC or Security SoC non-volatile storage on the + * device. If this bit is set, then this read is for the Security + * SoC non-volatile storage on the device. + */ + #define HWRM_NVM_RAW_DUMP_INPUT_FLAGS_SECURITY_SOC_NVM UINT32_C(0x1) + uint8_t unused_0[7]; } hwrm_nvm_raw_dump_input_t, *phwrm_nvm_raw_dump_input_t; /* hwrm_nvm_raw_dump_output (size:128b/16B) */ @@ -61827,9 +68347,9 @@ typedef struct hwrm_nvm_raw_dump_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -61892,9 +68412,9 @@ typedef struct hwrm_nvm_get_dir_entries_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -61956,9 +68476,9 @@ typedef struct hwrm_nvm_get_dir_info_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62012,7 +68532,8 @@ typedef struct hwrm_nvm_write_input { uint16_t dir_type; /* * Directory ordinal. - * The 0-based instance of the combined Directory Entry Type and Extension. + * The 0-based instance of the combined Directory Entry Type and + * Extension. */ uint16_t dir_ordinal; /* @@ -62060,13 +68581,14 @@ typedef struct hwrm_nvm_write_input { * The requested length of the allocated NVM for the item, in bytes. * This value may be greater than or equal to the specified data * length (dir_data_length). - * If this value is less than the specified data length, it will be ignored. - * The response will contain the actual allocated item length, + * If this value is less than the specified data length, it will be + * ignored. The response will contain the actual allocated item length, * which may be greater than the requested item length. * The purpose for allocating more than the required number of bytes * for an item's data is to pre-allocate extra storage (padding) to * accommodate the potential future growth of an item (e.g. upgraded - * firmware with a size increase, log growth, expanded configuration data). + * firmware with a size increase, log growth, expanded configuration + * data). */ uint32_t dir_item_length; /* @@ -62106,9 +68628,9 @@ typedef struct hwrm_nvm_write_output { uint8_t unused_0; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62216,9 +68738,9 @@ typedef struct hwrm_nvm_modify_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62320,9 +68842,9 @@ typedef struct hwrm_nvm_find_dir_entry_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62383,9 +68905,9 @@ typedef struct hwrm_nvm_erase_dir_entry_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62396,7 +68918,7 @@ typedef struct hwrm_nvm_erase_dir_entry_output { *************************/ -/* hwrm_nvm_get_dev_info_input (size:128b/16B) */ +/* hwrm_nvm_get_dev_info_input (size:192b/24B) */ typedef struct hwrm_nvm_get_dev_info_input { /* The HWRM command request type. */ @@ -62427,9 +68949,20 @@ typedef struct hwrm_nvm_get_dev_info_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used for + * secure boot.This bit is utilized to differentiate between + * device information for NIC or Security SoC non-volatile + * storage on the device. If this bit is set, then device + * information for the Security SoC non-volatile storage on the + * device. + */ + #define HWRM_NVM_GET_DEV_INFO_INPUT_FLAGS_SECURITY_SOC_NVM UINT32_C(0x1) + uint8_t unused_0[7]; } hwrm_nvm_get_dev_info_input_t, *phwrm_nvm_get_dev_info_input_t; -/* hwrm_nvm_get_dev_info_output (size:640b/80B) */ +/* hwrm_nvm_get_dev_info_output (size:768b/96B) */ typedef struct hwrm_nvm_get_dev_info_output { /* The specific error status for the command. */ @@ -62450,7 +68983,7 @@ typedef struct hwrm_nvm_get_dev_info_output { uint32_t nvram_size; uint32_t reserved_size; /* - * Available size that can be used, in bytes. Available size is the + * Available size that can be used, in bytes. Available size is the * NVRAM size take away the used size and reserved size. */ uint32_t available_size; @@ -62534,12 +69067,54 @@ typedef struct hwrm_nvm_get_dev_info_output { * of the roce firmware. */ uint16_t roce_fw_patch; + /* + * This field represents the major version of network control firmware, + * stored in the flash. + */ + uint16_t netctrl_fw_major; + /* + * This field represents the minor version of network control firmware, + * stored in the flash. + */ + uint16_t netctrl_fw_minor; + /* + * This field represents the build version of network control firmware, + * stored in the flash. + */ + uint16_t netctrl_fw_build; + /* + * This field can be used to represent firmware branches or customer + * specific releases tied to a specific (major, minor, build) version + * of the network control firmware. + */ + uint16_t netctrl_fw_patch; + /* + * This field represents the major version of SRT2 firmware, stored in + * the flash. + */ + uint16_t srt2_fw_major; + /* + * This field represents the minor version of SRT2 firmware, stored in + * the flash. + */ + uint16_t srt2_fw_minor; + /* + * This field represents the build version of SRT2 firmware, stored in + * the flash. + */ + uint16_t srt2_fw_build; + /* + * This field can be used to represent firmware branches or customer + * specific releases tied to a specific (major, minor, build) version + * of the SRT2 firmware. + */ + uint16_t srt2_fw_patch; uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62625,9 +69200,9 @@ typedef struct hwrm_nvm_mod_dir_entry_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62703,9 +69278,9 @@ typedef struct hwrm_nvm_verify_update_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62810,8 +69385,9 @@ typedef struct hwrm_nvm_install_update_output { uint16_t resp_len; /* * Bit-mask of successfully installed items. - * Bit-0 corresponding to the first packaged item, Bit-1 for the second item, etc. - * A value of 0 indicates that no items were successfully installed. + * Bit-0 corresponding to the first packaged item, Bit-1 for the second + * item, etc. A value of 0 indicates that no items were successfully + * installed. */ uint64_t installed_items; /* result is 8 b corresponding to BCMRETVAL error codes */ @@ -62905,9 +69481,9 @@ typedef struct hwrm_nvm_install_update_output { uint8_t unused_0[4]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -62987,9 +69563,9 @@ typedef struct hwrm_nvm_flush_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63079,8 +69655,8 @@ typedef struct hwrm_nvm_get_variable_input { uint16_t index_3; uint8_t flags; /* - * When this bit is set to 1, the factory default value will be returned, - * 0 returns the operational value. + * When this bit is set to 1, the factory default value will be + * returned, 0 returns the operational value. */ #define HWRM_NVM_GET_VARIABLE_INPUT_FLAGS_FACTORY_DFLT UINT32_C(0x1) uint8_t unused_0; @@ -63117,9 +69693,9 @@ typedef struct hwrm_nvm_get_variable_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63250,9 +69826,9 @@ typedef struct hwrm_nvm_set_variable_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63371,9 +69947,9 @@ typedef struct hwrm_nvm_validate_option_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63482,9 +70058,9 @@ typedef struct hwrm_nvm_factory_defaults_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63572,9 +70148,9 @@ typedef struct hwrm_nvm_req_arbitration_output { uint8_t unused_0[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63636,9 +70212,9 @@ typedef struct hwrm_nvm_defrag_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -63660,13 +70236,163 @@ typedef struct hwrm_nvm_defrag_cmd_err { uint8_t unused_0[7]; } hwrm_nvm_defrag_cmd_err_t, *phwrm_nvm_defrag_cmd_err_t; +/******************************* + * hwrm_nvm_get_vpd_field_info * + *******************************/ + + +/* hwrm_nvm_get_vpd_field_info_input (size:192b/24B) */ + +typedef struct hwrm_nvm_get_vpd_field_info_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * Tag ID of the requested field. To request the Product Name + * a value of [0x00, 0x82] should be used. All other fields + * would use the two byte hexadecimal value of the ASCII + * characters. The first letter of the ASCII keyword is recorded + * in tag_id[0] and the next letter in tag_id[1]. + */ + uint8_t tag_id[2]; + uint8_t unused_0[6]; +} hwrm_nvm_get_vpd_field_info_input_t, *phwrm_nvm_get_vpd_field_info_input_t; + +/* hwrm_nvm_get_vpd_field_info_output (size:2176b/272B) */ + +typedef struct hwrm_nvm_get_vpd_field_info_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Data retrieved from VPD field */ + uint8_t data[256]; + /* size of data retrieved in bytes */ + uint16_t data_len; + uint8_t unused_0[5]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_nvm_get_vpd_field_info_output_t, *phwrm_nvm_get_vpd_field_info_output_t; + +/******************************* + * hwrm_nvm_set_vpd_field_info * + *******************************/ + + +/* hwrm_nvm_set_vpd_field_info_input (size:256b/32B) */ + +typedef struct hwrm_nvm_set_vpd_field_info_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * This is the host address where + * VPD data value will be copied from + */ + uint64_t host_src_addr; + /* + * Tag ID of the requested field. To request the Product Name + * a value of [0x00, 0x82] should be used. All other fields + * would use the two byte hexadecimal value of the ASCII + * characters. The first letter of the ASCII keyword is recorded + * in tag_id[0] and the next letter in tag_id[1]. + */ + uint8_t tag_id[2]; + /* size of data in bytes */ + uint16_t data_len; + uint8_t unused_0[4]; +} hwrm_nvm_set_vpd_field_info_input_t, *phwrm_nvm_set_vpd_field_info_input_t; + +/* hwrm_nvm_set_vpd_field_info_output (size:128b/16B) */ + +typedef struct hwrm_nvm_set_vpd_field_info_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_nvm_set_vpd_field_info_output_t, *phwrm_nvm_set_vpd_field_info_output_t; + #define ROCE_SP_HSI_VERSION_MAJOR 1 #define ROCE_SP_HSI_VERSION_MINOR 8 #define ROCE_SP_HSI_VERSION_UPDATE 4 #define ROCE_SP_HSI_VERSION_STR "1.8.4" /* - * Following is the signature for ROCE_SP_HSI message field that indicates not - * applicable (All F's). Need to cast it the size of the field if needed. + * Following is the signature for ROCE_SP_HSI message field that indicates + * not applicable (All F's). Need to cast it the size of the field if + * needed. */ #define ROCE_SP_HSI_NA_SIGNATURE ((uint32_t)(-1)) @@ -63708,107 +70434,161 @@ typedef struct cmdq_base { * Create QP command allocates QP context with the specified * SQ, RQ/SRQ, CQ and other parameters. */ - #define CMDQ_BASE_OPCODE_CREATE_QP UINT32_C(0x1) + #define CMDQ_BASE_OPCODE_CREATE_QP UINT32_C(0x1) /* * Destroy QP command deletes the QP context and ceases * any further reference. */ - #define CMDQ_BASE_OPCODE_DESTROY_QP UINT32_C(0x2) + #define CMDQ_BASE_OPCODE_DESTROY_QP UINT32_C(0x2) /* * Modify QP command changes QP states and other QP specific * parameters. */ - #define CMDQ_BASE_OPCODE_MODIFY_QP UINT32_C(0x3) + #define CMDQ_BASE_OPCODE_MODIFY_QP UINT32_C(0x3) /* Query QP command retrieves info about the specified QP. */ - #define CMDQ_BASE_OPCODE_QUERY_QP UINT32_C(0x4) + #define CMDQ_BASE_OPCODE_QUERY_QP UINT32_C(0x4) /* Create SRQ command allocates a SRQ with the specified parameters. */ - #define CMDQ_BASE_OPCODE_CREATE_SRQ UINT32_C(0x5) + #define CMDQ_BASE_OPCODE_CREATE_SRQ UINT32_C(0x5) /* Destroy SRQ command deletes and flushes the specified SRQ. */ - #define CMDQ_BASE_OPCODE_DESTROY_SRQ UINT32_C(0x6) + #define CMDQ_BASE_OPCODE_DESTROY_SRQ UINT32_C(0x6) /* Query SRP command retrieves info about the specified SRQ. */ - #define CMDQ_BASE_OPCODE_QUERY_SRQ UINT32_C(0x8) + #define CMDQ_BASE_OPCODE_QUERY_SRQ UINT32_C(0x8) /* Create CQ command allocates a CQ with the specified parameters. */ - #define CMDQ_BASE_OPCODE_CREATE_CQ UINT32_C(0x9) + #define CMDQ_BASE_OPCODE_CREATE_CQ UINT32_C(0x9) /* Destroy CQ command deletes and flushes the specified CQ. */ - #define CMDQ_BASE_OPCODE_DESTROY_CQ UINT32_C(0xa) + #define CMDQ_BASE_OPCODE_DESTROY_CQ UINT32_C(0xa) /* Resize CQ command resizes the specified CQ. */ - #define CMDQ_BASE_OPCODE_RESIZE_CQ UINT32_C(0xc) + #define CMDQ_BASE_OPCODE_RESIZE_CQ UINT32_C(0xc) /* * Allocate MRW command allocates a MR/MW with the specified parameters * and returns the region's L_KEY/R_KEY */ - #define CMDQ_BASE_OPCODE_ALLOCATE_MRW UINT32_C(0xd) - /* De-allocate key command frees a MR/MW entry associated with the specified key. */ - #define CMDQ_BASE_OPCODE_DEALLOCATE_KEY UINT32_C(0xe) + #define CMDQ_BASE_OPCODE_ALLOCATE_MRW UINT32_C(0xd) + /* + * De-allocate key command frees a MR/MW entry associated with the + * specified key. + */ + #define CMDQ_BASE_OPCODE_DEALLOCATE_KEY UINT32_C(0xe) /* Register MR command registers memory to the specified MR. */ - #define CMDQ_BASE_OPCODE_REGISTER_MR UINT32_C(0xf) + #define CMDQ_BASE_OPCODE_REGISTER_MR UINT32_C(0xf) /* Deregister MR command de-registers memory from the specified MR. */ - #define CMDQ_BASE_OPCODE_DEREGISTER_MR UINT32_C(0x10) + #define CMDQ_BASE_OPCODE_DEREGISTER_MR UINT32_C(0x10) /* Add GID command adds a GID to the local address table. */ - #define CMDQ_BASE_OPCODE_ADD_GID UINT32_C(0x11) + #define CMDQ_BASE_OPCODE_ADD_GID UINT32_C(0x11) /* Delete GID command deletes a GID from the local address table. */ - #define CMDQ_BASE_OPCODE_DELETE_GID UINT32_C(0x12) + #define CMDQ_BASE_OPCODE_DELETE_GID UINT32_C(0x12) /* Modify GID command modifies a GID in the local address table. */ - #define CMDQ_BASE_OPCODE_MODIFY_GID UINT32_C(0x17) + #define CMDQ_BASE_OPCODE_MODIFY_GID UINT32_C(0x17) /* Query GID command queries a GID in the local address table. */ - #define CMDQ_BASE_OPCODE_QUERY_GID UINT32_C(0x18) + #define CMDQ_BASE_OPCODE_QUERY_GID UINT32_C(0x18) /* Create QP1 command allocates a QP1 only. */ - #define CMDQ_BASE_OPCODE_CREATE_QP1 UINT32_C(0x13) + #define CMDQ_BASE_OPCODE_CREATE_QP1 UINT32_C(0x13) /* Destroy QP1 command deletes and flushes the specified QP1. */ - #define CMDQ_BASE_OPCODE_DESTROY_QP1 UINT32_C(0x14) + #define CMDQ_BASE_OPCODE_DESTROY_QP1 UINT32_C(0x14) /* Create AH command allocates an AH with the specified parameters. */ - #define CMDQ_BASE_OPCODE_CREATE_AH UINT32_C(0x15) + #define CMDQ_BASE_OPCODE_CREATE_AH UINT32_C(0x15) /* Destroy AH command deletes the specified AH. */ - #define CMDQ_BASE_OPCODE_DESTROY_AH UINT32_C(0x16) + #define CMDQ_BASE_OPCODE_DESTROY_AH UINT32_C(0x16) /* * Initialize firmware command initializes the firmware with * the specified parameters. */ - #define CMDQ_BASE_OPCODE_INITIALIZE_FW UINT32_C(0x80) + #define CMDQ_BASE_OPCODE_INITIALIZE_FW UINT32_C(0x80) /* De-initialize firmware command deinitializes the firmware. */ - #define CMDQ_BASE_OPCODE_DEINITIALIZE_FW UINT32_C(0x81) + #define CMDQ_BASE_OPCODE_DEINITIALIZE_FW UINT32_C(0x81) /* Stop the function */ - #define CMDQ_BASE_OPCODE_STOP_FUNC UINT32_C(0x82) + #define CMDQ_BASE_OPCODE_STOP_FUNC UINT32_C(0x82) /* Query the HW capabilities for the function. */ - #define CMDQ_BASE_OPCODE_QUERY_FUNC UINT32_C(0x83) + #define CMDQ_BASE_OPCODE_QUERY_FUNC UINT32_C(0x83) /* * Set the following resources for the function: * - Max QP, CQ, MR+MW, SRQ per PF * - Max QP, CQ, MR+MW, SRQ per VF */ - #define CMDQ_BASE_OPCODE_SET_FUNC_RESOURCES UINT32_C(0x84) - /* Read the current state of any internal resource context. Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_READ_CONTEXT UINT32_C(0x85) - /* Send a request from VF to pass a command to the PF. VF HSI is suspended until the PF returns the response */ - #define CMDQ_BASE_OPCODE_VF_BACKCHANNEL_REQUEST UINT32_C(0x86) - /* Read VF memory (primarily to get the backchannel request blob). Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_READ_VF_MEMORY UINT32_C(0x87) - /* Write VF memory (primarily to put the backchannel response blob), and reenable VF HSI (post a CAG completion to it). Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_COMPLETE_VF_REQUEST UINT32_C(0x88) - /* Extend resource (QPC, MRW, CQ, SRQ) array, after the host allocates more. Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_EXTEND_CONTEXT_ARRRAY UINT32_C(0x89) + #define CMDQ_BASE_OPCODE_SET_FUNC_RESOURCES UINT32_C(0x84) + /* + * Read the current state of any internal resource context. Can only be + * issued from a PF. + */ + #define CMDQ_BASE_OPCODE_READ_CONTEXT UINT32_C(0x85) + /* + * Send a request from VF to pass a command to the PF. VF HSI is + * suspended until the PF returns the response + */ + #define CMDQ_BASE_OPCODE_VF_BACKCHANNEL_REQUEST UINT32_C(0x86) + /* + * Read VF memory (primarily to get the backchannel request blob). Can + * only be issued from a PF. + */ + #define CMDQ_BASE_OPCODE_READ_VF_MEMORY UINT32_C(0x87) + /* + * Write VF memory (primarily to put the backchannel response blob), + * and reenable VF HSI (post a CAG completion to it). Can only be + * issued from a PF. + */ + #define CMDQ_BASE_OPCODE_COMPLETE_VF_REQUEST UINT32_C(0x88) + /* + * Deprecated. + * Extend resource (QPC, MRW, CQ, SRQ) array, after the host allocates + * more. Can only be issued from a PF. + */ + #define CMDQ_BASE_OPCODE_EXTEND_CONTEXT_ARRAY_DEPRECATED UINT32_C(0x89) /* Map TC to COS. Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_MAP_TC_TO_COS UINT32_C(0x8a) + #define CMDQ_BASE_OPCODE_MAP_TC_TO_COS UINT32_C(0x8a) /* Query version. */ - #define CMDQ_BASE_OPCODE_QUERY_VERSION UINT32_C(0x8b) + #define CMDQ_BASE_OPCODE_QUERY_VERSION UINT32_C(0x8b) /* Modify congestion control. Can only be issued from a PF. */ - #define CMDQ_BASE_OPCODE_MODIFY_ROCE_CC UINT32_C(0x8c) + #define CMDQ_BASE_OPCODE_MODIFY_ROCE_CC UINT32_C(0x8c) /* Query congestion control. */ - #define CMDQ_BASE_OPCODE_QUERY_ROCE_CC UINT32_C(0x8d) + #define CMDQ_BASE_OPCODE_QUERY_ROCE_CC UINT32_C(0x8d) /* Query RoCE statistics. */ - #define CMDQ_BASE_OPCODE_QUERY_ROCE_STATS UINT32_C(0x8e) + #define CMDQ_BASE_OPCODE_QUERY_ROCE_STATS UINT32_C(0x8e) /* Set LAG mode. */ - #define CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE UINT32_C(0x8f) + #define CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE UINT32_C(0x8f) /* Modify CQ */ - #define CMDQ_BASE_OPCODE_MODIFY_CQ UINT32_C(0x90) + #define CMDQ_BASE_OPCODE_MODIFY_CQ UINT32_C(0x90) /* - * Query QP for a PF other than the requesting PF. Also can query for more - * than one QP. + * Query QP for a PF other than the requesting PF. Also can query for + * more than one QP. */ - #define CMDQ_BASE_OPCODE_QUERY_QP_EXTEND UINT32_C(0x91) + #define CMDQ_BASE_OPCODE_QUERY_QP_EXTEND UINT32_C(0x91) /* Query extended RoCE statistics. */ - #define CMDQ_BASE_OPCODE_QUERY_ROCE_STATS_EXT UINT32_C(0x92) - #define CMDQ_BASE_OPCODE_LAST CMDQ_BASE_OPCODE_QUERY_ROCE_STATS_EXT + #define CMDQ_BASE_OPCODE_QUERY_ROCE_STATS_EXT UINT32_C(0x92) + /* + * This command updates the QP context id ranges on the PF, + * to orchestrate QP context id range migration. + * This command is valid for devices that + * support the pseudo-static QP allocation feature. + */ + #define CMDQ_BASE_OPCODE_ORCHESTRATE_QID_MIGRATION UINT32_C(0x93) + /* + * This command allocates a batch of the requested count of QPs + * in a sequential range. + */ + #define CMDQ_BASE_OPCODE_CREATE_QP_BATCH UINT32_C(0x94) + /* + * This command deletes a batch of the requested count of QPs. + * The starting QP ID can be specified to request a batch deletion + * of a sequential range. + */ + #define CMDQ_BASE_OPCODE_DESTROY_QP_BATCH UINT32_C(0x95) + /* + * This command allocates an extended RoCE statistics context + * that supports periodic DMA to a host address. The extended + * statistics context id can be assigned by the driver + * via `create_qp`, `create_qp_batch`, or `modify_qp` to a specific QP, + * a subset of QPs or to all QPs of a specific function. + * These statistics can be queried via `query_roce_stats_ext_v2`. + */ + #define CMDQ_BASE_OPCODE_ALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x96) + /* This command deallocates an extended RoCE statistics context. */ + #define CMDQ_BASE_OPCODE_DEALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x97) + /* + * This command queries extended RoCE statistics for context + * allocated via `allocate_roce_stats_ext_ctx`. + */ + #define CMDQ_BASE_OPCODE_QUERY_ROCE_STATS_EXT_V2 UINT32_C(0x98) + #define CMDQ_BASE_OPCODE_LAST CMDQ_BASE_OPCODE_QUERY_ROCE_STATS_EXT_V2 /* Size of the command in 16-byte units. */ uint8_t cmd_size; /* Flags and attribs of the command. */ @@ -63853,6 +70633,390 @@ typedef struct creq_base { uint8_t reserved48[6]; } creq_base_t, *pcreq_base_t; +/* creq_resp_sb_hdr (size:64b/8B) */ + +typedef struct creq_resp_sb_hdr { + /* Command opcode. */ + uint8_t opcode; + /* Query QP command response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_QP UINT32_C(0x4) + /* Query SRQ command response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_SRQ UINT32_C(0x8) + /* Query GID command response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_GID UINT32_C(0x18) + /* Query info PF command response */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_FUNC UINT32_C(0x83) + /* Query version response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_VERSION UINT32_C(0x8b) + /* Query congestion control response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_ROCE_CC UINT32_C(0x8d) + /* Query RoCE statistics response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_ROCE_STATS UINT32_C(0x8e) + /* Query QP extended response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_QP_EXTEND UINT32_C(0x91) + /* Query extended RoCE statistics response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_ROCE_STATS_EXT UINT32_C(0x92) + /* Query extended RoCE statistics v2 response. */ + #define CREQ_RESP_SB_HDR_OPCODE_QUERY_ROCE_STATS_EXT_V2 UINT32_C(0x98) + #define CREQ_RESP_SB_HDR_OPCODE_LAST CREQ_RESP_SB_HDR_OPCODE_QUERY_ROCE_STATS_EXT_V2 + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; +} creq_resp_sb_hdr_t, *pcreq_resp_sb_hdr_t; + +/* + * Structure to be used for the qp_params array of + * the `create_qp_batch` command. + */ +/* create_qp_batch_data (size:768b/96B) */ + +typedef struct create_qp_batch_data { + /* QP handle. */ + uint64_t qp_handle; + /* Create QP flags. */ + uint32_t qp_flags; + /* + * SRQ is used. + * This flag is not supported on express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_SRQ_USED UINT32_C(0x1) + /* post CQE for all SQ WQEs. */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_FORCE_COMPLETION UINT32_C(0x2) + /* This QP can use reserved L_Key */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_RESERVED_LKEY_ENABLE UINT32_C(0x4) + /* This QP can fast register physical memory */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_FR_PMR_ENABLED UINT32_C(0x8) + /* This QP can send variable sized WQEs. */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED UINT32_C(0x10) + /* + * WQEs with inline data sent on this QP are able to flow + * through an optimized transmit path to lower latency. This + * transmit path is opportunistic and not guaranteed to always + * occur. + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_OPTIMIZED_TRANSMIT_ENABLED UINT32_C(0x20) + /* + * For UD QPs the default responder CQE format is `cq_res_ud`. + * This flag specifies the `cq_res_ud_cfa` format to be used + * instead. + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_RESPONDER_UD_CQE_WITH_CFA UINT32_C(0x40) + /* + * This QP must be included in the extended RoCE statistics + * that can be queried via `query_roce_stats_ext`. + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_EXT_STATS_ENABLED UINT32_C(0x80) + /* This QP uses express mode. */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_EXPRESS_MODE_ENABLED UINT32_C(0x100) + /* This QP uses the steering tag specified in the command. */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_STEERING_TAG_VALID UINT32_C(0x200) + /* + * This QP can be used for RDMA Read or Atomic operations. + * This value is used to optimize metadata memory allocation + * when the device supports `internal_queue_memory` feature. + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_RDMA_READ_OR_ATOMICS_USED UINT32_C(0x400) + /* + * This QP must be included in the extended RoCE statistics context + * specified in the field `ext_stats_ctx_id` + */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_EXT_STATS_CTX_VALID UINT32_C(0x800) + /* The schq_id field passed in by the caller is valid. */ + #define CREATE_QP_BATCH_DATA_QP_FLAGS_SCHQ_ID_VALID UINT32_C(0x1000) + #define CREATE_QP_BATCH_DATA_QP_FLAGS_LAST CREATE_QP_BATCH_DATA_QP_FLAGS_SCHQ_ID_VALID + /* Supported QP types. */ + uint8_t type; + /* Reliable Connection. */ + #define CREATE_QP_BATCH_DATA_TYPE_RC UINT32_C(0x2) + /* Unreliable Datagram. */ + #define CREATE_QP_BATCH_DATA_TYPE_UD UINT32_C(0x4) + /* Raw Ethertype. */ + #define CREATE_QP_BATCH_DATA_TYPE_RAW_ETHERTYPE UINT32_C(0x6) + /* General Services Interface on QP1 over UD. */ + #define CREATE_QP_BATCH_DATA_TYPE_GSI UINT32_C(0x7) + #define CREATE_QP_BATCH_DATA_TYPE_LAST CREATE_QP_BATCH_DATA_TYPE_GSI + uint8_t sq_pg_size_sq_lvl; + /* + * SQ PBL indirect levels. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_SQ_LVL_MASK UINT32_C(0xf) + #define CREATE_QP_BATCH_DATA_SQ_LVL_SFT 0 + /* PBL pointer is physical start address. */ + #define CREATE_QP_BATCH_DATA_SQ_LVL_LVL_0 UINT32_C(0x0) + /* PBL pointer points to PTE table. */ + #define CREATE_QP_BATCH_DATA_SQ_LVL_LVL_1 UINT32_C(0x1) + /* + * PBL pointer points to PDE table with each entry pointing to + * PTE tables. + */ + #define CREATE_QP_BATCH_DATA_SQ_LVL_LVL_2 UINT32_C(0x2) + #define CREATE_QP_BATCH_DATA_SQ_LVL_LAST CREATE_QP_BATCH_DATA_SQ_LVL_LVL_2 + /* + * SQ page size. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_MASK UINT32_C(0xf0) + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_SFT 4 + /* 4KB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_4K (UINT32_C(0x0) << 4) + /* 8KB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_8K (UINT32_C(0x1) << 4) + /* 64KB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_64K (UINT32_C(0x2) << 4) + /* 2MB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_2M (UINT32_C(0x3) << 4) + /* 8MB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_8M (UINT32_C(0x4) << 4) + /* 1GB. */ + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) + #define CREATE_QP_BATCH_DATA_SQ_PG_SIZE_LAST CREATE_QP_BATCH_DATA_SQ_PG_SIZE_PG_1G + uint8_t rq_pg_size_rq_lvl; + /* + * RQ PBL indirect levels. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_RQ_LVL_MASK UINT32_C(0xf) + #define CREATE_QP_BATCH_DATA_RQ_LVL_SFT 0 + /* PBL pointer is physical start address. */ + #define CREATE_QP_BATCH_DATA_RQ_LVL_LVL_0 UINT32_C(0x0) + /* PBL pointer points to PTE table. */ + #define CREATE_QP_BATCH_DATA_RQ_LVL_LVL_1 UINT32_C(0x1) + /* + * PBL pointer points to PDE table with each entry pointing to + * PTE tables. + */ + #define CREATE_QP_BATCH_DATA_RQ_LVL_LVL_2 UINT32_C(0x2) + #define CREATE_QP_BATCH_DATA_RQ_LVL_LAST CREATE_QP_BATCH_DATA_RQ_LVL_LVL_2 + /* + * RQ page size. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_MASK UINT32_C(0xf0) + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_SFT 4 + /* 4KB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_4K (UINT32_C(0x0) << 4) + /* 8KB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_8K (UINT32_C(0x1) << 4) + /* 64KB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_64K (UINT32_C(0x2) << 4) + /* 2MB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_2M (UINT32_C(0x3) << 4) + /* 8MB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_8M (UINT32_C(0x4) << 4) + /* 1GB. */ + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) + #define CREATE_QP_BATCH_DATA_RQ_PG_SIZE_LAST CREATE_QP_BATCH_DATA_RQ_PG_SIZE_PG_1G + uint8_t unused_0; + /* Doorbell page index. */ + uint32_t dpi; + /* + * When the SQ is configured to use variable-size WQE, 'sq_size' + * denotes the SQ size with a unit of 16B. When the SQ is configured + * to use fixed-size WQE, 'sq_size' denotes the max number of SQ WQEs. + */ + uint32_t sq_size; + /* Max number of RQ wqes. */ + uint32_t rq_size; + uint16_t sq_fwo_sq_sge; + /* + * Max send SGEs per SWQE. This is only applicable to fixed-size + * WQE support. On variable-size WQE, this is ignored. + */ + #define CREATE_QP_BATCH_DATA_SQ_SGE_MASK UINT32_C(0xf) + #define CREATE_QP_BATCH_DATA_SQ_SGE_SFT 0 + /* + * Offset of First WQE in the first SQ page, in 128 byte units. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_SQ_FWO_MASK UINT32_C(0xfff0) + #define CREATE_QP_BATCH_DATA_SQ_FWO_SFT 4 + uint16_t rq_fwo_rq_sge; + /* + * Max recv SGEs per RWQE. + * On chips with variable-size WQE support, a value of zero implies + * 30 SGEs. + */ + #define CREATE_QP_BATCH_DATA_RQ_SGE_MASK UINT32_C(0xf) + #define CREATE_QP_BATCH_DATA_RQ_SGE_SFT 0 + /* + * Offset of First WQE in the first RQ page, in 128 byte units. + * This field is ignored for express mode QPs. + */ + #define CREATE_QP_BATCH_DATA_RQ_FWO_MASK UINT32_C(0xfff0) + #define CREATE_QP_BATCH_DATA_RQ_FWO_SFT 4 + /* Send CQ context id. */ + uint32_t scq_cid; + /* Receive CQ context id. */ + uint32_t rcq_cid; + /* SRQ context id. */ + uint32_t srq_cid; + /* Protection domain id. */ + uint32_t pd_id; + /* + * SQ PBL physical address. + * This field is ignored for express mode QPs. + */ + uint64_t sq_pbl; + /* + * RQ PBL physical address. + * This field is ignored for express mode QPs. + */ + uint64_t rq_pbl; + /* + * IRRQ address. This field is ignored on devices that + * support the `internal_queue_memory` feature. + */ + uint64_t irrq_addr; + /* + * ORRQ address. This field is ignored on devices that + * support the `internal_queue_memory` feature. + */ + uint64_t orrq_addr; + /* + * xid to use for the non-QP1 QP. + * The requested xid must be within the valid range + * of the predetermined assignment scheme of the + * pseudo static QP allocation feature. The valid range + * for the data QPs is determined by the start_qid and + * max_qp fields of query_func response. When the value is zero, + * firmware will automatically choose an xid from its free pool. + * QP1 allocation, indicated by specifying `type` field as gsi, + * must specify a request_xid as zero. + * This field is ignored on devices that do not support + * the pseudo static QP allocation feature. + */ + uint32_t request_xid; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + /* + * This value is used to optimize metadata memory allocation when + * the device supports `internal_queue_memory` feature. + * When the SQ is configured to use variable-size WQEs, the SQ size is + * only specified in units of 16 Bytes. This value hints the max number + * of WQEs that would ever be present on the SQ. + */ + uint16_t sq_max_num_wqes; + /* Extended RoCE statistics context id. */ + uint32_t ext_stats_ctx_id; + /* + * Identifies the new scheduling queue to associate with + * the RoCE QP. A value of zero indicates that the QP is being + * created with the default scheduling queue. Can only be specified + * by the PF driver. VFs get assigned a scheduling queue based on PF + * configuration (via HWRM_FUNC_CFG). Specified scheduling queue id is + * allocated by firmware (via HWRM_SCHQ_ALLOC) when the device supports + * the `scheduling queue` feature. + */ + uint16_t schq_id; + uint16_t reserved16; +} create_qp_batch_data_t, *pcreate_qp_batch_data_t; + +/* Periodic extended RoCE statistics context DMA to host. */ +/* roce_stats_ext_ctx (size:1856b/232B) */ + +typedef struct roce_stats_ext_ctx { + /* Number of transmitted Atomic request packets without errors. */ + uint64_t tx_atomic_req_pkts; + /* Number of transmitted Read request packets without errors. */ + uint64_t tx_read_req_pkts; + /* Number of transmitted Read response packets without errors. */ + uint64_t tx_read_res_pkts; + /* Number of transmitted Write request packets without errors. */ + uint64_t tx_write_req_pkts; + /* Number of transmitted RC Send packets without errors. */ + uint64_t tx_rc_send_req_pkts; + /* + * Number of transmitted UD Send (including QP1) packets + * without errors. + */ + uint64_t tx_ud_send_req_pkts; + /* Number of transmitted CNPs. Includes DCN_CNPs. */ + uint64_t tx_cnp_pkts; + /* + * Number of transmitted RoCE packets. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t tx_roce_pkts; + /* + * Number of transmitted RoCE header and payload bytes. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t tx_roce_bytes; + /* + * Number of drops that occurred to lack of buffers. + * This count includes RC sends, RC writes with immediate, + * UD sends, RawEth, and QP1 packets dropped due to lack of buffers. + */ + uint64_t rx_out_of_buffer_pkts; + /* Number of packets that were received out of sequence. */ + uint64_t rx_out_of_sequence_pkts; + /* + * Number of duplicate read/atomic requests resulting in responder + * hardware retransmission. + */ + uint64_t dup_req; + /* + * Number of missing response packets resulting in hardware + * retransmission. + */ + uint64_t missing_resp; + /* + * Number of sequence error NAKs received resulting in hardware + * retransmission. + */ + uint64_t seq_err_naks_rcvd; + /* Number of RNR NAKs received resulting in hardware retransmission. */ + uint64_t rnr_naks_rcvd; + /* Number of timeouts resulting in hardware retransmission. */ + uint64_t to_retransmits; + /* Number of received Atomic request packets without errors. */ + uint64_t rx_atomic_req_pkts; + /* Number of received Read request packets without errors. */ + uint64_t rx_read_req_pkts; + /* Number of received Read response packets without errors. */ + uint64_t rx_read_res_pkts; + /* Number of received Write request packets without errors. */ + uint64_t rx_write_req_pkts; + /* Number of received RC Send packets without errors. */ + uint64_t rx_rc_send_pkts; + /* Number of received UD Send packets without errors. */ + uint64_t rx_ud_send_pkts; + /* Number of received DCN payload cut packets. */ + uint64_t rx_dcn_payload_cut; + /* Number of received ECN-marked packets. */ + uint64_t rx_ecn_marked_pkts; + /* Number of received CNP packets. Includes DCN_CNPs. */ + uint64_t rx_cnp_pkts; + /* + * Number of received RoCE packets including RoCE packets with errors. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t rx_roce_pkts; + /* + * Number of received RoCE header and payload bytes including RoCE + * packets with errors. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t rx_roce_bytes; + /* + * Number of received RoCE packets without errors. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t rx_roce_good_pkts; + /* + * Number of received RoCE header and payload bytes without errors. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t rx_roce_good_bytes; +} roce_stats_ext_ctx_t, *proce_stats_ext_ctx_t; + /***************** * query_version * *****************/ @@ -63935,7 +71099,7 @@ typedef struct creq_query_version_resp { *****************/ -/* cmdq_initialize_fw (size:896b/112B) */ +/* cmdq_initialize_fw (size:1024b/128B) */ typedef struct cmdq_initialize_fw { /* Command opcode. */ @@ -63960,6 +71124,15 @@ typedef struct cmdq_initialize_fw { * feature is supported. */ #define CMDQ_INITIALIZE_FW_FLAGS_HW_REQUESTER_RETX_SUPPORTED UINT32_C(0x2) + /* When set, the driver version is provided. */ + #define CMDQ_INITIALIZE_FW_FLAGS_DRV_VERSION UINT32_C(0x4) + /* When set, driver supports optimizing Modify QP operation. */ + #define CMDQ_INITIALIZE_FW_FLAGS_OPTIMIZE_MODIFY_QP_SUPPORTED UINT32_C(0x8) + /* + * When set, the VF RoCE resources will be managed by the L2 + * driver via func_cfg. + */ + #define CMDQ_INITIALIZE_FW_FLAGS_L2_VF_RESOURCE_MGMT UINT32_C(0x10) /* Driver supplied handle to associate the command and the response. */ uint16_t cookie; /* Size of the response buffer in 16-byte units. */ @@ -63975,7 +71148,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_QPC_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_QPC_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to + * PTE tables. + */ #define CMDQ_INITIALIZE_FW_QPC_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_QPC_LVL_LAST CMDQ_INITIALIZE_FW_QPC_LVL_LVL_2 /* QPC page size. */ @@ -64002,7 +71178,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_MRW_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_MRW_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_INITIALIZE_FW_MRW_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_MRW_LVL_LAST CMDQ_INITIALIZE_FW_MRW_LVL_LVL_2 /* MRW page size. */ @@ -64029,7 +71208,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_SRQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_SRQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_INITIALIZE_FW_SRQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_SRQ_LVL_LAST CMDQ_INITIALIZE_FW_SRQ_LVL_LVL_2 /* SRQ page size. */ @@ -64056,7 +71238,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_CQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_CQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_INITIALIZE_FW_CQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_CQ_LVL_LAST CMDQ_INITIALIZE_FW_CQ_LVL_LVL_2 /* CQ page size. */ @@ -64083,7 +71268,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_TQM_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_TQM_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_INITIALIZE_FW_TQM_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_TQM_LVL_LAST CMDQ_INITIALIZE_FW_TQM_LVL_LVL_2 /* TQM page size. */ @@ -64110,7 +71298,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_TIM_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_INITIALIZE_FW_TIM_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_INITIALIZE_FW_TIM_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_INITIALIZE_FW_TIM_LVL_LAST CMDQ_INITIALIZE_FW_TIM_LVL_LVL_2 /* TIM page size. */ @@ -64130,7 +71321,10 @@ typedef struct cmdq_initialize_fw { #define CMDQ_INITIALIZE_FW_TIM_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) #define CMDQ_INITIALIZE_FW_TIM_PG_SIZE_LAST CMDQ_INITIALIZE_FW_TIM_PG_SIZE_PG_1G uint16_t log2_dbr_pg_size; - /* Log base 2 of DBR page size - 12. 0 for 4KB. HW supported values are enumerated below. */ + /* + * Log base 2 of DBR page size - 12. 0 for 4KB. HW supported values + * are enumerated below. + */ #define CMDQ_INITIALIZE_FW_LOG2_DBR_PG_SIZE_MASK UINT32_C(0xf) #define CMDQ_INITIALIZE_FW_LOG2_DBR_PG_SIZE_SFT 0 /* 4KB. */ @@ -64181,15 +71375,30 @@ typedef struct cmdq_initialize_fw { uint64_t tqm_page_dir; /* TIM page directory. */ uint64_t tim_page_dir; - /* Number of QPs. */ + /* + * Number of QPs. This field is ignored when the backing store HWRM's + * are used. + */ uint32_t number_of_qp; - /* Number of MRWs. */ + /* + * Number of MRWs. This field is ignored when the backing store HWRM's + * are used. + */ uint32_t number_of_mrw; - /* Number of SRQs. */ + /* + * Number of SRQs. This field is ignored when the backing store HWRM's + * are used. + */ uint32_t number_of_srq; - /* Number of CQs. */ + /* + * Number of CQs. This field is ignored when the backing store HWRM's + * are used. + */ uint32_t number_of_cq; - /* Number of QPs per VF. */ + /* + * Number of QPs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_qp_per_vf; /* * If the MR/AV split reservation flag is not set, then this field @@ -64204,16 +71413,44 @@ typedef struct cmdq_initialize_fw { * `max_av_per_vf`. The granularity of these values is defined by * the `mrav_num_entries_unit` field returned by the * `backing_store_qcaps` command. + * + * This field must be set to zero when the flag, l2_vf_resource_mgmt, + * is set and RoCE SRIOV is enabled. */ uint32_t max_mrw_per_vf; - /* Number of SRQs per VF. */ + /* + * Number of SRQs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_srq_per_vf; - /* Number of CQs per VF. */ + /* + * Number of CQs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_cq_per_vf; - /* Number of GIDs per VF. */ + /* + * Number of GIDs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_gid_per_vf; /* Statistics context index for this function. */ uint32_t stat_ctx_id; + /* The driver HSI major version number. */ + uint8_t drv_hsi_ver_maj; + /* The driver HSI minor version number. */ + uint8_t drv_hsi_ver_min; + /* The driver HSI update version number. */ + uint8_t drv_hsi_ver_upd; + /* This is the 40bit unused. */ + uint8_t unused40[5]; + /* The driver build major version number. */ + uint16_t drv_build_ver_maj; + /* The driver build minor version number. */ + uint16_t drv_build_ver_min; + /* The driver build update version number. */ + uint16_t drv_build_ver_upd; + /* The driver build patch version number. */ + uint16_t drv_build_ver_patch; } cmdq_initialize_fw_t, *pcmdq_initialize_fw_t; /* creq_initialize_fw_resp (size:128b/16B) */ @@ -64319,7 +71556,7 @@ typedef struct creq_deinitialize_fw_resp { *************/ -/* cmdq_create_qp (size:768b/96B) */ +/* cmdq_create_qp (size:896b/112B) */ typedef struct cmdq_create_qp { /* Command opcode. */ @@ -64345,7 +71582,10 @@ typedef struct cmdq_create_qp { uint64_t qp_handle; /* Create QP flags. */ uint32_t qp_flags; - /* SRQ is used. */ + /* + * SRQ is used. + * This flag is not supported on express mode QPs. + */ #define CMDQ_CREATE_QP_QP_FLAGS_SRQ_USED UINT32_C(0x1) /* post CQE for all SQ WQEs. */ #define CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION UINT32_C(0x2) @@ -64373,7 +71613,24 @@ typedef struct cmdq_create_qp { * that can be queried via `query_roce_stats_ext`. */ #define CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED UINT32_C(0x80) - #define CMDQ_CREATE_QP_QP_FLAGS_LAST CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED + /* This QP uses express mode. */ + #define CMDQ_CREATE_QP_QP_FLAGS_EXPRESS_MODE_ENABLED UINT32_C(0x100) + /* This QP uses the steering tag specified in the command. */ + #define CMDQ_CREATE_QP_QP_FLAGS_STEERING_TAG_VALID UINT32_C(0x200) + /* + * This QP can be used for RDMA Read or Atomic operations. + * This value is used to optimize metadata memory allocation + * when the device supports `internal_queue_memory` feature. + */ + #define CMDQ_CREATE_QP_QP_FLAGS_RDMA_READ_OR_ATOMICS_USED UINT32_C(0x400) + /* + * This QP must be included in the extended RoCE statistics context + * specified in the field `ext_stats_ctx_id` + */ + #define CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_CTX_VALID UINT32_C(0x800) + /* The schq_id field passed in by the caller is valid. */ + #define CMDQ_CREATE_QP_QP_FLAGS_SCHQ_ID_VALID UINT32_C(0x1000) + #define CMDQ_CREATE_QP_QP_FLAGS_LAST CMDQ_CREATE_QP_QP_FLAGS_SCHQ_ID_VALID /* Supported QP types. */ uint8_t type; /* Reliable Connection. */ @@ -64386,17 +71643,26 @@ typedef struct cmdq_create_qp { #define CMDQ_CREATE_QP_TYPE_GSI UINT32_C(0x7) #define CMDQ_CREATE_QP_TYPE_LAST CMDQ_CREATE_QP_TYPE_GSI uint8_t sq_pg_size_sq_lvl; - /* SQ PBL indirect levels. */ + /* + * SQ PBL indirect levels. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_SQ_LVL_MASK UINT32_C(0xf) #define CMDQ_CREATE_QP_SQ_LVL_SFT 0 /* PBL pointer is physical start address. */ #define CMDQ_CREATE_QP_SQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_QP_SQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to + * PTE tables. + */ #define CMDQ_CREATE_QP_SQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_QP_SQ_LVL_LAST CMDQ_CREATE_QP_SQ_LVL_LVL_2 - /* SQ page size. */ + /* + * SQ page size. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_SQ_PG_SIZE_MASK UINT32_C(0xf0) #define CMDQ_CREATE_QP_SQ_PG_SIZE_SFT 4 /* 4KB. */ @@ -64413,17 +71679,26 @@ typedef struct cmdq_create_qp { #define CMDQ_CREATE_QP_SQ_PG_SIZE_PG_1G (UINT32_C(0x5) << 4) #define CMDQ_CREATE_QP_SQ_PG_SIZE_LAST CMDQ_CREATE_QP_SQ_PG_SIZE_PG_1G uint8_t rq_pg_size_rq_lvl; - /* RQ PBL indirect levels. */ + /* + * RQ PBL indirect levels. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_RQ_LVL_MASK UINT32_C(0xf) #define CMDQ_CREATE_QP_RQ_LVL_SFT 0 /* PBL pointer is physical start address. */ #define CMDQ_CREATE_QP_RQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_QP_RQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to + * PTE tables. + */ #define CMDQ_CREATE_QP_RQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_QP_RQ_LVL_LAST CMDQ_CREATE_QP_RQ_LVL_LVL_2 - /* RQ page size. */ + /* + * RQ page size. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_RQ_PG_SIZE_MASK UINT32_C(0xf0) #define CMDQ_CREATE_QP_RQ_PG_SIZE_SFT 4 /* 4KB. */ @@ -64442,25 +71717,39 @@ typedef struct cmdq_create_qp { uint8_t unused_0; /* Doorbell page index. */ uint32_t dpi; - /* Max number of SQ wqes. */ + /* + * When the SQ is configured to use variable-size WQE, 'sq_size' + * denotes the SQ size with a unit of 16B. When the SQ is configured + * to use fixed-size WQE, 'sq_size' denotes the max number of SQ WQEs. + */ uint32_t sq_size; /* Max number of RQ wqes. */ uint32_t rq_size; uint16_t sq_fwo_sq_sge; - /* Max send SGEs per SWQE. */ + /* + * Max send SGEs per SWQE. This is only applicable to fixed-size + * WQE support. On variable-size WQE, this is ignored. + */ #define CMDQ_CREATE_QP_SQ_SGE_MASK UINT32_C(0xf) #define CMDQ_CREATE_QP_SQ_SGE_SFT 0 - /* Offset of First WQE in the first SQ page, in 128 byte units */ + /* + * Offset of First WQE in the first SQ page, in 128 byte units. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_SQ_FWO_MASK UINT32_C(0xfff0) #define CMDQ_CREATE_QP_SQ_FWO_SFT 4 uint16_t rq_fwo_rq_sge; /* * Max recv SGEs per RWQE. - * On chips with variable-size WQE support, a value of zero implies 30 SGEs. + * On chips with variable-size WQE support, a value of zero implies + * 30 SGEs. */ #define CMDQ_CREATE_QP_RQ_SGE_MASK UINT32_C(0xf) #define CMDQ_CREATE_QP_RQ_SGE_SFT 0 - /* Offset of First WQE in the first RQ page, in 128 byte units */ + /* + * Offset of First WQE in the first RQ page, in 128 byte units. + * This field is ignored for express mode QPs. + */ #define CMDQ_CREATE_QP_RQ_FWO_MASK UINT32_C(0xfff0) #define CMDQ_CREATE_QP_RQ_FWO_SFT 4 /* Send CQ context id. */ @@ -64471,14 +71760,63 @@ typedef struct cmdq_create_qp { uint32_t srq_cid; /* Protection domain id. */ uint32_t pd_id; - /* SQ PBL physical address. */ + /* + * SQ PBL physical address. + * This field is ignored for express mode QPs. + */ uint64_t sq_pbl; - /* RQ PBL physical address. */ + /* + * RQ PBL physical address. + * This field is ignored for express mode QPs. + */ uint64_t rq_pbl; - /* IRRQ address. */ + /* + * IRRQ address. This field is ignored on devices that + * support the `internal_queue_memory` feature. + */ uint64_t irrq_addr; - /* ORRQ address. */ + /* + * ORRQ address. This field is ignored on devices that + * support the `internal_queue_memory` feature. + */ uint64_t orrq_addr; + /* + * xid to use for the non-QP1 QP. + * The requested xid must be within the valid range + * of the predetermined assignment scheme of the + * pseudo static QP allocation feature. The valid range + * for the data QPs is determined by the start_qid and + * max_qp fields of query_func response. When the value is zero, + * firmware will automatically choose an xid from its free pool. + * QP1 allocation, indicated by specifying `type` field as gsi, + * must specify a request_xid as zero. + * This field is ignored on devices that do not support + * the pseudo static QP allocation feature. + */ + uint32_t request_xid; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + /* + * This value is used to optimize metadata memory allocation when + * the device supports `internal_queue_memory` feature. + * When the SQ is configured to use variable-size WQEs, the SQ size is + * only specified in units of 16 Bytes. This value hints the max number + * of WQEs that would ever be present on the SQ. + */ + uint16_t sq_max_num_wqes; + /* Extended RoCE statistics context id. */ + uint32_t ext_stats_ctx_id; + /* + * Identifies the new scheduling queue to associate with + * the RoCE QP. A value of zero indicates that the QP is being + * created with the default scheduling queue. Can only be specified + * by the PF driver. VFs get assigned a scheduling queue based on PF + * configuration (via HWRM_FUNC_CFG). Specified scheduling queue id is + * allocated by firmware (via HWRM_SCHQ_ALLOC) when the device supports + * the `scheduling queue` feature. + */ + uint16_t schq_id; + uint16_t reserved16; } cmdq_create_qp_t, *pcmdq_create_qp_t; /* creq_create_qp_resp (size:128b/16B) */ @@ -64597,7 +71935,7 @@ typedef struct creq_destroy_qp_resp { *************/ -/* cmdq_modify_qp (size:1024b/128B) */ +/* cmdq_modify_qp (size:1152b/144B) */ typedef struct cmdq_modify_qp { /* Command opcode. */ @@ -64612,11 +71950,37 @@ typedef struct cmdq_modify_qp { uint8_t cmd_size; /* Flags and attribs of the command. */ uint16_t flags; + /* + * This field, used by firmware for optimizing Modify QP operation, + * must be set when the driver has indicated support for the + * optimize_modify_qp_supported feature in cmdq_initialize_fw and + * when QP Type RC is configured to use SRQ. + */ + #define CMDQ_MODIFY_QP_FLAGS_SRQ_USED UINT32_C(0x1) + /* + * This field must be set when the driver has indicated that the + * qp should be excluded from udcc sessions. + */ + #define CMDQ_MODIFY_QP_FLAGS_EXCLUDE_QP_UDCC UINT32_C(0x2) /* Driver supplied handle to associate the command and the response. */ uint16_t cookie; /* Size of the response buffer in 16-byte units. */ uint8_t resp_size; - uint8_t reserved8; + /* + * This field, used by firmware for optimizing Modify QP operation, + * must be set when the driver has indicated support for the + * optimize_modify_qp_supported feature in cmdq_initialize_fw. + */ + uint8_t qp_type; + /* Reliable Connection. */ + #define CMDQ_MODIFY_QP_QP_TYPE_RC UINT32_C(0x2) + /* Unreliable Datagram. */ + #define CMDQ_MODIFY_QP_QP_TYPE_UD UINT32_C(0x4) + /* Raw Ethertype. */ + #define CMDQ_MODIFY_QP_QP_TYPE_RAW_ETHERTYPE UINT32_C(0x6) + /* General Services Interface on QP1 over UD. */ + #define CMDQ_MODIFY_QP_QP_TYPE_GSI UINT32_C(0x7) + #define CMDQ_MODIFY_QP_QP_TYPE_LAST CMDQ_MODIFY_QP_QP_TYPE_GSI /* Host address of the response. */ uint64_t resp_addr; /* Modify mask signifies the field that is requesting the change. */ @@ -64730,7 +72094,10 @@ typedef struct cmdq_modify_qp { #define CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE UINT32_C(0x2) /* Remote read access. */ #define CMDQ_MODIFY_QP_ACCESS_REMOTE_READ UINT32_C(0x4) - /* Remote atomic access. */ + /* + * Remote atomic access. Applicable to devices that support + * Atomic operations. + */ #define CMDQ_MODIFY_QP_ACCESS_REMOTE_ATOMIC UINT32_C(0x8) /* P_KEY. */ uint16_t pkey; @@ -64811,7 +72178,7 @@ typedef struct cmdq_modify_qp { uint16_t sq_sge; /* Max recv SGEs per RWQE. */ uint16_t rq_sge; - /* Max inline data length (upto 120 bytes). */ + /* Max inline data length (up to 120 bytes). */ uint32_t max_inline_data; /* Destination QP id. */ uint32_t dest_qp_id; @@ -64832,6 +72199,29 @@ typedef struct cmdq_modify_qp { uint64_t irrq_addr; /* ORRQ address. */ uint64_t orrq_addr; + /* + * Extended Modify mask signifies the field that is requesting the + * change. + */ + uint32_t ext_modify_mask; + /* Extended RoCE statistics context id change */ + #define CMDQ_MODIFY_QP_EXT_MODIFY_MASK_EXT_STATS_CTX UINT32_C(0x1) + /* The schq_id field is valid */ + #define CMDQ_MODIFY_QP_EXT_MODIFY_MASK_SCHQ_ID_VALID UINT32_C(0x2) + /* Extended RoCE statistics context id. */ + uint32_t ext_stats_ctx_id; + /* + * Identifies the new scheduling queue to associate to the RoCE QP. + * A value of zero indicates that the QP is being modified to use + * the default scheduling queue. Specified scheduling queue id is + * allocated by firmware (via HWRM_SCHQ_ALLOC) when the device supports + * the `scheduling queue` feature. + */ + uint16_t schq_id; + /* unused_0 is 16 b */ + uint16_t unused_0; + /* reserved32 is 32 b */ + uint32_t reserved32; } cmdq_modify_qp_t, *pcmdq_modify_qp_t; /* creq_modify_qp_resp (size:128b/16B) */ @@ -65016,7 +72406,12 @@ typedef struct creq_query_qp_resp_sb { uint16_t pkey; /* Q_KEY. */ uint32_t qkey; - uint32_t reserved32; + /* + * UDP source port used in RoCEv2 packets. Valid only when + * change_udp_src_port_wqe_supported feature is advertised. + */ + uint16_t udp_src_port; + uint16_t reserved16; /* Destination GID. */ uint32_t dgid[4]; /* Flow label. */ @@ -65083,7 +72478,7 @@ typedef struct creq_query_qp_resp_sb { uint16_t sq_sge; /* Max recv SGEs per RWQE (NOT SUPPORTED BY HARDWARE). */ uint16_t rq_sge; - /* Max inline data length (upto 120 bytes). */ + /* Max inline data length (up to 120 bytes). */ uint32_t max_inline_data; /* Destination QP id. */ uint32_t dest_qp_id; @@ -65116,8 +72511,8 @@ typedef struct cmdq_query_qp_extend { /* Command opcode. */ uint8_t opcode; /* - * Query QP extend command retrieves info about multiple QPs associated - * with a specific PF. + * Query QP extend command retrieves info about multiple QPs + * associated with a specific PF. */ #define CMDQ_QUERY_QP_EXTEND_OPCODE_QUERY_QP_EXTEND UINT32_C(0x91) #define CMDQ_QUERY_QP_EXTEND_OPCODE_LAST CMDQ_QUERY_QP_EXTEND_OPCODE_QUERY_QP_EXTEND @@ -65129,7 +72524,10 @@ typedef struct cmdq_query_qp_extend { uint16_t cookie; /* Size of the response buffer in 16-byte units. */ uint8_t resp_size; - /* Number of QPs for which FW needs to query and provide info back to host. */ + /* + * Number of QPs for which FW needs to query and provide info back to + * host. + */ uint8_t num_qps; /* Host address of the response. */ uint64_t resp_addr; @@ -65144,8 +72542,8 @@ typedef struct cmdq_query_qp_extend { /* When set the vf_num is valid. */ #define CMDQ_QUERY_QP_EXTEND_VF_VALID UINT32_C(0x1000000) /* - * This is the current index where firmware left off for query qp. Driver - * will pass this back in the next query_qp_extend command. + * This is the current index where firmware left off for query qp. + * Driver will pass this back in the next query_qp_extend command. */ uint32_t current_index; } cmdq_query_qp_extend_t, *pcmdq_query_qp_extend_t; @@ -65186,8 +72584,8 @@ typedef struct creq_query_qp_extend_resp { #define CREQ_QUERY_QP_EXTEND_RESP_EVENT_LAST CREQ_QUERY_QP_EXTEND_RESP_EVENT_QUERY_QP_EXTEND uint16_t reserved16; /* - * This is the current index where firmware left off for query qp. Driver - * will pass this back in the next query_qp_extend command. + * This is the current index where firmware left off for query qp. + * Driver will pass this back in the next query_qp_extend command. */ uint32_t current_index; } creq_query_qp_extend_resp_t, *pcreq_query_qp_extend_resp_t; @@ -65257,7 +72655,7 @@ typedef struct creq_query_qp_extend_resp_sb { uint32_t dest_qp_id; /* Statistic collection ID allocated for this QP. */ uint8_t stat_collection_id; - uint8_t reservred_8; + uint8_t reserved2_8; uint16_t reserved_16; } creq_query_qp_extend_resp_sb_t, *pcreq_query_qp_extend_resp_sb_t; @@ -65386,7 +72784,7 @@ typedef struct creq_query_qp_extend_resp_sb_tlv { uint32_t dest_qp_id; /* Statistic collection ID allocated for this QP. */ uint8_t stat_collection_id; - uint8_t reservred_8; + uint8_t reserved2_8; uint16_t reserved_16; } creq_query_qp_extend_resp_sb_tlv_t, *pcreq_query_qp_extend_resp_sb_tlv_t; @@ -65395,7 +72793,7 @@ typedef struct creq_query_qp_extend_resp_sb_tlv { **************/ -/* cmdq_create_srq (size:384b/48B) */ +/* cmdq_create_srq (size:512b/64B) */ typedef struct cmdq_create_srq { /* Command opcode. */ @@ -65407,6 +72805,8 @@ typedef struct cmdq_create_srq { uint8_t cmd_size; /* Flags and attribs of the command. */ uint16_t flags; + /* This SRQ uses the steering tag specified in the command. */ + #define CMDQ_CREATE_SRQ_FLAGS_STEERING_TAG_VALID UINT32_C(0x1) /* Driver supplied handle to associate the command and the response. */ uint16_t cookie; /* Size of the response buffer in 16-byte units. */ @@ -65424,7 +72824,10 @@ typedef struct cmdq_create_srq { #define CMDQ_CREATE_SRQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_SRQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_CREATE_SRQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_SRQ_LVL_LAST CMDQ_CREATE_SRQ_LVL_LVL_2 /* page size. */ @@ -65455,14 +72858,27 @@ typedef struct cmdq_create_srq { #define CMDQ_CREATE_SRQ_UNUSED4_SFT 12 /* Max number of SRQ wqes. */ uint16_t srq_size; - /* Offset of first WQE in the first page of SRQ, in 128 byte units */ uint16_t srq_fwo; + /* Offset of first WQE in the first page of SRQ, in 128 byte units */ + #define CMDQ_CREATE_SRQ_SRQ_FWO_MASK UINT32_C(0xfff) + #define CMDQ_CREATE_SRQ_SRQ_FWO_SFT 0 + /* + * Max SGEs per SRQ WQE. This field is enabled if flag, + * create_srq_sge_supported, is set in query_func response. + */ + #define CMDQ_CREATE_SRQ_SRQ_SGE_MASK UINT32_C(0xf000) + #define CMDQ_CREATE_SRQ_SRQ_SGE_SFT 12 /* Doorbell page index. */ uint32_t dpi; /* Protection domain id. */ uint32_t pd_id; /* RQ PBL physical address. */ uint64_t pbl; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + uint8_t reserved48[6]; + /* reserved64 is 64 b */ + uint64_t reserved64; } cmdq_create_srq_t, *pcmdq_create_srq_t; /* creq_create_srq_resp (size:128b/16B) */ @@ -65568,7 +72984,10 @@ typedef struct creq_destroy_srq_resp { uint16_t enable_for_arm[3]; #define CREQ_DESTROY_SRQ_RESP_UNUSED0_MASK UINT32_C(0xffff) #define CREQ_DESTROY_SRQ_RESP_UNUSED0_SFT 0 - /* Set to 1 if this SRQ is allowed to be armed for threshold async event */ + /* + * Set to 1 if this SRQ is allowed to be armed for threshold async + * event + */ #define CREQ_DESTROY_SRQ_RESP_ENABLE_FOR_ARM_MASK UINT32_C(0x30000) #define CREQ_DESTROY_SRQ_RESP_ENABLE_FOR_ARM_SFT 16 } creq_destroy_srq_resp_t, *pcreq_destroy_srq_resp_t; @@ -65671,7 +73090,7 @@ typedef struct creq_query_srq_resp_sb { *************/ -/* cmdq_create_cq (size:384b/48B) */ +/* cmdq_create_cq (size:512b/64B) */ typedef struct cmdq_create_cq { /* Command opcode. */ @@ -65694,6 +73113,25 @@ typedef struct cmdq_create_cq { * by the driver when HW based doorbell recovery is enabled. */ #define CMDQ_CREATE_CQ_FLAGS_DISABLE_CQ_OVERFLOW_DETECTION UINT32_C(0x1) + /* This CQ uses the steering tag specified in the command. */ + #define CMDQ_CREATE_CQ_FLAGS_STEERING_TAG_VALID UINT32_C(0x2) + /* + * This CQ uses the infinite CQ mode. + * In the infinite CQ mode, all CQEs are written to the same + * address. Note that this mode implies a HW client is + * handling each entry instantly and avoiding overwrites. + * The following limitations apply when this mode is enabled: + * -cq_size field must be 1 + * -disable_cq_overflow_detection flag must be true. + * -the CQ will never be armed. + * -the consumer index of CQ will never be changed + */ + #define CMDQ_CREATE_CQ_FLAGS_INFINITE_CQ_MODE UINT32_C(0x4) + /* + * This CQ uses coalescing data specified in the command. + * This feature is not supported if infinite_cq_mode is also enabled. + */ + #define CMDQ_CREATE_CQ_FLAGS_COALESCING_VALID UINT32_C(0x8) /* Driver supplied handle to associate the command and the response. */ uint16_t cookie; /* Size of the response buffer in 16-byte units. */ @@ -65711,7 +73149,10 @@ typedef struct cmdq_create_cq { #define CMDQ_CREATE_CQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_CQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_CREATE_CQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_CQ_LVL_LAST CMDQ_CREATE_CQ_LVL_LVL_2 /* page size. */ @@ -65746,6 +73187,45 @@ typedef struct cmdq_create_cq { uint32_t cq_size; /* CQ PBL physical address. */ uint64_t pbl; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + uint8_t reserved16[2]; + uint32_t coalescing; + /* + * Buffer Max time before flushing buffer (units of 1us). This + * specifies the maximum time before completion buffers are + * flushed out to host memory even if the number of coalesced + * buffers is less than the threshold. buf_maxtime is 9 bits. + */ + #define CMDQ_CREATE_CQ_BUF_MAXTIME_MASK UINT32_C(0x1ff) + #define CMDQ_CREATE_CQ_BUF_MAXTIME_SFT 0 + /* + * This specifies the number of buffers coalesced before sending + * to memory during normal operation. Buffer unit is 16B + * completions. normal_maxbuf is 5 bits. + */ + #define CMDQ_CREATE_CQ_NORMAL_MAXBUF_MASK UINT32_C(0x3e00) + #define CMDQ_CREATE_CQ_NORMAL_MAXBUF_SFT 9 + /* + * This specifies the number of buffers coalesced before sending + * to memory when the interrupt is masked. Buffer unit is 16B + * completions. during_maxbuf is 5 bits. + */ + #define CMDQ_CREATE_CQ_DURING_MAXBUF_MASK UINT32_C(0x7c000) + #define CMDQ_CREATE_CQ_DURING_MAXBUF_SFT 14 + /* + * This field is used to enable ring for global idle mode interrupt + * generation. This mode will generate a notification (interrupt) + * if armed when only one completion has been generated if the chip + * is globally idle as determined by the device. + * enable_ring_idle_mode is 1 bit. + */ + #define CMDQ_CREATE_CQ_ENABLE_RING_IDLE_MODE UINT32_C(0x80000) + /* unused12 is 12 b */ + #define CMDQ_CREATE_CQ_UNUSED12_MASK UINT32_C(0xfff00000) + #define CMDQ_CREATE_CQ_UNUSED12_SFT 20 + /* reserved64 is 64 b */ + uint64_t reserved64; } cmdq_create_cq_t, *pcmdq_create_cq_t; /* creq_create_cq_resp (size:128b/16B) */ @@ -65858,8 +73338,9 @@ typedef struct creq_destroy_cq_resp { #define CREQ_DESTROY_CQ_RESP_CQ_ARM_LVL_MASK UINT32_C(0x3) #define CREQ_DESTROY_CQ_RESP_CQ_ARM_LVL_SFT 0 /* - * The total number of CNQ events for the CQ, incremented on each CNQ event for the CQ - * (including firmware-generated CQ error notification). + * The total number of CNQ events for the CQ, incremented on each CNQ + * event for the CQ (including firmware-generated CQ error + * notification). */ uint16_t total_cnq_events; uint16_t reserved16; @@ -65899,7 +73380,10 @@ typedef struct cmdq_resize_cq { #define CMDQ_RESIZE_CQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_RESIZE_CQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_RESIZE_CQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_RESIZE_CQ_LVL_LAST CMDQ_RESIZE_CQ_LVL_LVL_2 /* page size. */ @@ -66085,8 +73569,8 @@ typedef struct cmdq_allocate_mrw { /* Command opcode. */ uint8_t opcode; /* - * Allocate MRW command allocates a MR/MW with the specified parameters - * and returns the region's L_KEY/R_KEY + * Allocate MRW command allocates a MR/MW with the specified + * parameters and returns the region's L_KEY/R_KEY */ #define CMDQ_ALLOCATE_MRW_OPCODE_ALLOCATE_MRW UINT32_C(0xd) #define CMDQ_ALLOCATE_MRW_OPCODE_LAST CMDQ_ALLOCATE_MRW_OPCODE_ALLOCATE_MRW @@ -66108,25 +73592,30 @@ typedef struct cmdq_allocate_mrw { #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MASK UINT32_C(0xf) #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_SFT 0 /* Allocate Memory Region */ - #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR UINT32_C(0x0) + #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR UINT32_C(0x0) /* Allocate Physical Memory Region */ - #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR UINT32_C(0x1) + #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR UINT32_C(0x1) /* Allocate Memory Window (type 1) */ - #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 UINT32_C(0x2) + #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 UINT32_C(0x2) /* Allocate Memory Window (type 2A) */ - #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A UINT32_C(0x3) + #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A UINT32_C(0x3) /* Allocate Memory Window (type 2B) */ - #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B UINT32_C(0x4) + #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B UINT32_C(0x4) #define CMDQ_ALLOCATE_MRW_MRW_FLAGS_LAST CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B - /* unused4 is 4 b */ - #define CMDQ_ALLOCATE_MRW_UNUSED4_MASK UINT32_C(0xf0) - #define CMDQ_ALLOCATE_MRW_UNUSED4_SFT 4 + /* + * This Memory Region / Memory Window uses the + * steering tag specified in the command. + */ + #define CMDQ_ALLOCATE_MRW_STEERING_TAG_VALID UINT32_C(0x10) + /* unused3 is 3 b */ + #define CMDQ_ALLOCATE_MRW_UNUSED3_MASK UINT32_C(0xe0) + #define CMDQ_ALLOCATE_MRW_UNUSED3_SFT 5 /* Access flags. */ uint8_t access; /* Consumer owns the key */ #define CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY UINT32_C(0x20) - /* unused16 is 16 b */ - uint16_t unused16; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; /* Protection domain id. */ uint32_t pd_id; } cmdq_allocate_mrw_t, *pcmdq_allocate_mrw_t; @@ -66178,7 +73667,10 @@ typedef struct creq_allocate_mrw_resp { typedef struct cmdq_deallocate_key { /* Command opcode. */ uint8_t opcode; - /* De-allocate key command frees a MR/MW entry associated with the specified key. */ + /* + * De-allocate key command frees a MR/MW entry associated with the + * specified key. + */ #define CMDQ_DEALLOCATE_KEY_OPCODE_DEALLOCATE_KEY UINT32_C(0xe) #define CMDQ_DEALLOCATE_KEY_OPCODE_LAST CMDQ_DEALLOCATE_KEY_OPCODE_DEALLOCATE_KEY /* Size of the command in 16-byte units. */ @@ -66252,12 +73744,16 @@ typedef struct creq_deallocate_key_resp { #define CREQ_DEALLOCATE_KEY_RESP_EVENT_LAST CREQ_DEALLOCATE_KEY_RESP_EVENT_DEALLOCATE_KEY uint16_t reserved16; /* - * This is advisory data to facilitate eventual destruction of lingering memory regions in Windows. - * For memory window, it contains non-zero HWID of a region this window was bound to (without the 8-bit key portion). - * The host may check if the region is lingering in destroyed state and try to destroy it now. - * For memory region, if deallocation fails because there are windows bound to this region, this field will contain - * approximate number of those windows. This number is read from the context right before the - * deregistration is attempted and can potentially be slightly different from the current number. + * This is advisory data to facilitate eventual destruction of + * lingering memory regions in Windows. For memory window, it contains + * non-zero HWID of a region this window was bound to (without the + * 8-bit key portion). The host may check if the region is lingering in + * destroyed state and try to destroy it now. For memory region, if + * deallocation fails because there are windows bound to this region, + * this field will contain approximate number of those windows. This + * number is read from the context right before the deregistration is + * attempted and can potentially be slightly different from the current + * number. */ uint32_t bound_window_info; } creq_deallocate_key_resp_t, *pcreq_deallocate_key_resp_t; @@ -66267,7 +73763,7 @@ typedef struct creq_deallocate_key_resp { ***************/ -/* cmdq_register_mr (size:384b/48B) */ +/* cmdq_register_mr (size:512b/64B) */ typedef struct cmdq_register_mr { /* Command opcode. */ @@ -66285,7 +73781,15 @@ typedef struct cmdq_register_mr { * the `key` field doesn't hold a valid L_KEY and is instead * overloaded to hold the Protection Domain ID `pd_id`. */ - #define CMDQ_REGISTER_MR_FLAGS_ALLOC_MR UINT32_C(0x1) + #define CMDQ_REGISTER_MR_FLAGS_ALLOC_MR UINT32_C(0x1) + /* + * This MR uses the steering tag specified in the command. + * This flag can only be enabled when the command is used + * to allocate a new MR first. + */ + #define CMDQ_REGISTER_MR_FLAGS_STEERING_TAG_VALID UINT32_C(0x2) + /* When set, enable per MR relaxed ordering support. */ + #define CMDQ_REGISTER_MR_FLAGS_ENABLE_RO UINT32_C(0x4) /* Driver supplied handle to associate the command and the response. */ uint16_t cookie; /* Size of the response buffer in 16-byte units. */ @@ -66301,10 +73805,16 @@ typedef struct cmdq_register_mr { #define CMDQ_REGISTER_MR_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_REGISTER_MR_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_REGISTER_MR_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_REGISTER_MR_LVL_LAST CMDQ_REGISTER_MR_LVL_LVL_2 - /* Log base 2 of page size; 12 is the minimum for 4KB. HW supported values are enumerated below. */ + /* + * Log base 2 of page size; 12 is the minimum for 4KB. HW supported + * values are enumerated below. + */ #define CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK UINT32_C(0x7c) #define CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT 2 /* 4KB. */ @@ -66341,7 +73851,10 @@ typedef struct cmdq_register_mr { /* Indicate Zero Based Virtual Address (ZBVA). */ #define CMDQ_REGISTER_MR_ACCESS_ZERO_BASED UINT32_C(0x20) uint16_t log2_pbl_pg_size; - /* Log base 2 of PBL page size; 12 is the minimum for 4KB. HW supported values are enumerated below */ + /* + * Log base 2 of PBL page size; 12 is the minimum for 4KB. HW + * supported values are enumerated below + */ #define CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK UINT32_C(0x1f) #define CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT 0 /* 4KB. */ @@ -66377,6 +73890,11 @@ typedef struct cmdq_register_mr { uint64_t va; /* Size of the MR. */ uint64_t mr_size; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + uint8_t reserved48[6]; + /* reserved64 is 64 b */ + uint64_t reserved64; } cmdq_register_mr_t, *pcmdq_register_mr_t; /* creq_register_mr_resp (size:128b/16B) */ @@ -66481,9 +73999,11 @@ typedef struct creq_deregister_mr_resp { #define CREQ_DEREGISTER_MR_RESP_EVENT_LAST CREQ_DEREGISTER_MR_RESP_EVENT_DEREGISTER_MR uint16_t reserved16; /* - * If deregister fails because there are windows bound to this region, this field will contain - * approximate number of those windows. This number is read from the context right before the - * deregistration is attempted and can potentially be slightly different from the current number. + * If deregister fails because there are windows bound to this region, + * this field will contain approximate number of those windows. This + * number is read from the context right before the deregistration is + * attempted and can potentially be slightly different from the current + * number. */ uint32_t bound_windows; } creq_deregister_mr_resp_t, *pcreq_deregister_mr_resp_t; @@ -66543,7 +74063,10 @@ typedef struct cmdq_add_gid { /* TPID = Configurable 3. */ #define CMDQ_ADD_GID_VLAN_TPID_TPID_CFG3 (UINT32_C(0x7) << 12) #define CMDQ_ADD_GID_VLAN_TPID_LAST CMDQ_ADD_GID_VLAN_TPID_TPID_CFG3 - /* Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE header. */ + /* + * Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE + * header. + */ #define CMDQ_ADD_GID_VLAN_VLAN_EN UINT32_C(0x8000) /* Identifier field in the IP header. */ uint16_t ipid; @@ -66554,7 +74077,10 @@ typedef struct cmdq_add_gid { /* stats_ctx_id is 15 b */ #define CMDQ_ADD_GID_STATS_CTX_STATS_CTX_ID_MASK UINT32_C(0x7fff) #define CMDQ_ADD_GID_STATS_CTX_STATS_CTX_ID_SFT 0 - /* Setting this bit to 1 enables use of own stats context ID instead of per-function */ + /* + * Setting this bit to 1 enables use of own stats context ID + * instead of per-function. + */ #define CMDQ_ADD_GID_STATS_CTX_STATS_CTX_VALID UINT32_C(0x8000) uint32_t unused_0; } cmdq_add_gid_t, *pcmdq_add_gid_t; @@ -66715,7 +74241,10 @@ typedef struct cmdq_modify_gid { /* TPID = Configurable 3. */ #define CMDQ_MODIFY_GID_VLAN_TPID_TPID_CFG3 (UINT32_C(0x7) << 12) #define CMDQ_MODIFY_GID_VLAN_TPID_LAST CMDQ_MODIFY_GID_VLAN_TPID_TPID_CFG3 - /* Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE header. */ + /* + * Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE + * header. + */ #define CMDQ_MODIFY_GID_VLAN_VLAN_EN UINT32_C(0x8000) /* Identifier field in the IP header. */ uint16_t ipid; @@ -66726,7 +74255,10 @@ typedef struct cmdq_modify_gid { /* stats_ctx_id is 15 b */ #define CMDQ_MODIFY_GID_STATS_CTX_STATS_CTX_ID_MASK UINT32_C(0x7fff) #define CMDQ_MODIFY_GID_STATS_CTX_STATS_CTX_ID_SFT 0 - /* Setting this bit to 1 enables use of own stats context ID instead of per-function */ + /* + * Setting this bit to 1 enables use of own stats context ID + * instead of per-function. + */ #define CMDQ_MODIFY_GID_STATS_CTX_STATS_CTX_VALID UINT32_C(0x8000) uint16_t unused_0; } cmdq_modify_gid_t, *pcmdq_modify_gid_t; @@ -66884,7 +74416,10 @@ typedef struct creq_query_gid_resp_sb { /* TPID = Configurable 3. */ #define CREQ_QUERY_GID_RESP_SB_VLAN_TPID_TPID_CFG3 (UINT32_C(0x7) << 12) #define CREQ_QUERY_GID_RESP_SB_VLAN_TPID_LAST CREQ_QUERY_GID_RESP_SB_VLAN_TPID_TPID_CFG3 - /* Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE header. */ + /* + * Setting this bit to 1 enables insertion of a VLAN Tag to a RoCE + * header. + */ #define CREQ_QUERY_GID_RESP_SB_VLAN_VLAN_EN UINT32_C(0x8000) /* Identifier field in the IP header. */ uint16_t ipid; @@ -66941,7 +74476,10 @@ typedef struct cmdq_create_qp1 { #define CMDQ_CREATE_QP1_SQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_QP1_SQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_CREATE_QP1_SQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_QP1_SQ_LVL_LAST CMDQ_CREATE_QP1_SQ_LVL_LVL_2 /* SQ page size. */ @@ -66968,7 +74506,10 @@ typedef struct cmdq_create_qp1 { #define CMDQ_CREATE_QP1_RQ_LVL_LVL_0 UINT32_C(0x0) /* PBL pointer points to PTE table. */ #define CMDQ_CREATE_QP1_RQ_LVL_LVL_1 UINT32_C(0x1) - /* PBL pointer points to PDE table with each entry pointing to PTE tables. */ + /* + * PBL pointer points to PDE table with each entry pointing to PTE + * tables. + */ #define CMDQ_CREATE_QP1_RQ_LVL_LVL_2 UINT32_C(0x2) #define CMDQ_CREATE_QP1_RQ_LVL_LAST CMDQ_CREATE_QP1_RQ_LVL_LVL_2 /* RQ page size. */ @@ -67306,16 +74847,17 @@ typedef struct cmdq_query_roce_stats { /* Flags and attribs of the command. */ uint16_t flags; /* - * When this bit is set FW will use the collection_id to extract RoCE statistics. - * If function_id is also specified the FW will return stats corresponding to the - * collection for the function_id specified. + * When this bit is set FW will use the collection_id to extract + * RoCE statistics. If function_id is also specified the FW will + * return stats corresponding to the collection for the function_id + * specified. */ #define CMDQ_QUERY_ROCE_STATS_FLAGS_COLLECTION_ID UINT32_C(0x1) /* - * When this bit is set FW will use the function_id to extract RoCE statistics. - * When collection is specified then FW will return the specific collection - * stats and if the collection is not specified then FW will return the default - * stats which will be for all QPs. + * When this bit is set FW will use the function_id to extract RoCE + * statistics. When collection is specified then FW will return the + * specific collection stats and if the collection is not specified + * then FW will return the default stats which will be for all QPs. */ #define CMDQ_QUERY_ROCE_STATS_FLAGS_FUNCTION_ID UINT32_C(0x2) /* Driver supplied handle to associate the command and the response. */ @@ -67377,7 +74919,7 @@ typedef struct creq_query_roce_stats_resp { } creq_query_roce_stats_resp_t, *pcreq_query_roce_stats_resp_t; /* Query RoCE Stats command response side buffer structure. */ -/* creq_query_roce_stats_resp_sb (size:2944b/368B) */ +/* creq_query_roce_stats_resp_sb (size:3072b/384B) */ typedef struct creq_query_roce_stats_resp_sb { /* Command opcode. */ @@ -67482,6 +75024,10 @@ typedef struct creq_query_roce_stats_resp_sb { uint64_t active_qp_count_p2; /* active_qp_count_p3 is 64 b */ uint64_t active_qp_count_p3; + /* express mode SQ doorbell overflow error 64b counter. */ + uint64_t xp_sq_overflow_err; + /* express mode RQ doorbell overflow error 64b counter. */ + uint64_t xp_rq_overflow_error; } creq_query_roce_stats_resp_sb_t, *pcreq_query_roce_stats_resp_sb_t; /************************ @@ -67502,16 +75048,17 @@ typedef struct cmdq_query_roce_stats_ext { /* Flags and attribs of the command. */ uint16_t flags; /* - * When this bit is set FW will use the collection_id to extract RoCE statistics. - * If function_id is also specified the FW will return stats corresponding to the - * collection for the function_id specified. + * When this bit is set FW will use the collection_id to extract + * RoCE statistics. If function_id is also specified the FW will + * return stats corresponding to the collection for the function_id + * specified. */ #define CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_COLLECTION_ID UINT32_C(0x1) /* - * When this bit is set FW will use the function_id to extract RoCE statistics. - * When collection is specified then FW will return the specific collection - * stats and if the collection is not specified then FW will return the default - * stats which will be for all QPs. + * When this bit is set FW will use the function_id to extract RoCE + * statistics. When collection is specified then FW will return the + * specific collection stats and if the collection is not specified + * then FW will return the default stats which will be for all QPs. */ #define CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_FUNCTION_ID UINT32_C(0x2) /* Driver supplied handle to associate the command and the response. */ @@ -67573,7 +75120,7 @@ typedef struct creq_query_roce_stats_ext_resp { } creq_query_roce_stats_ext_resp_t, *pcreq_query_roce_stats_ext_resp_t; /* Query extended RoCE Stats command response side buffer structure. */ -/* creq_query_roce_stats_ext_resp_sb (size:1984b/248B) */ +/* creq_query_roce_stats_ext_resp_sb (size:2304b/288B) */ typedef struct creq_query_roce_stats_ext_resp_sb { /* Command opcode. */ @@ -67689,7 +75236,8 @@ typedef struct creq_query_roce_stats_ext_resp_sb { */ uint64_t to_retransmit; /* - * Number of duplicate read requests resulting in HW retransmission. + * Number of duplicate read/atomic requests resulting in HW + * retransmission. * This counter is only applicable for devices that support * hardware based retransmission. */ @@ -67702,6 +75250,39 @@ typedef struct creq_query_roce_stats_ext_resp_sb { uint64_t rx_dcn_payload_cut; /* Number of transmitted packets that bypassed the transmit engine. */ uint64_t te_bypassed; + /* + * Number of transmitted DCN CNP packets. + * This counter is only applicable for devices that support + * the DCN Payload Cut feature. + */ + uint64_t tx_dcn_cnp; + /* + * Number of received DCN CNP packets. + * This counter is only applicable for devices that support + * the DCN Payload Cut feature. + */ + uint64_t rx_dcn_cnp; + /* + * Number of received DCN payload cut packets. + * This counter is only applicable for devices that support + * the DCN Payload Cut feature. + */ + uint64_t rx_payload_cut; + /* + * Number of received DCN payload cut packets that are ignored + * because they failed the PSN checks. + * This counter is only applicable for devices that support + * the DCN Payload Cut feature. + */ + uint64_t rx_payload_cut_ignored; + /* + * Number of received DCN CNP packets that are ignored either + * because the ECN is not enabled on the QP or the ECN is enabled + * but the CNP packets do not pass the packet validation checks. + * This counter is only applicable for devices that support + * the DCN Payload Cut feature. + */ + uint64_t rx_dcn_cnp_ignored; } creq_query_roce_stats_ext_resp_sb_t, *pcreq_query_roce_stats_ext_resp_sb_t; /************** @@ -67768,7 +75349,7 @@ typedef struct creq_query_func_resp { } creq_query_func_resp_t, *pcreq_query_func_resp_t; /* Query function command response side buffer structure. */ -/* creq_query_func_resp_sb (size:1088b/136B) */ +/* creq_query_func_resp_sb (size:1280b/160B) */ typedef struct creq_query_func_resp_sb { /* Command opcode. */ @@ -67787,17 +75368,26 @@ typedef struct creq_query_func_resp_sb { uint8_t reserved8; /* Max MR size supported. */ uint64_t max_mr_size; - /* Max QP supported. */ + /* + * Max QP supported. + * For devices that support the pseudo static allocation scheme, + * this count: + * -excludes the QP1 count. + * -includes the count of QPs that can be migrated from the other PF + * Therefore, during normal operation when both PFs are active, + * the supported number of RoCE QPs for each of the PF is half + * of the advertised value. + */ uint32_t max_qp; /* Max WQEs per QP. */ uint16_t max_qp_wr; /* Device capability flags. */ uint16_t dev_cap_flags; /* Allow QP resizing. */ - #define CREQ_QUERY_FUNC_RESP_SB_RESIZE_QP UINT32_C(0x1) + #define CREQ_QUERY_FUNC_RESP_SB_RESIZE_QP UINT32_C(0x1) /* Specifies Congestion Control (CC) generation. */ #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_MASK UINT32_C(0xe) - #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_SFT 1 + #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_SFT 1 /* * Includes support for DCTCP and TCP CC algorithms, * enabling operation in networks where PFC is enabled. @@ -67808,7 +75398,8 @@ typedef struct creq_query_func_resp_sb { * enabling fast ramp up and convergence, * as well as operation in networks where PFC is not enabled. * Includes a number of parameters that are different from cc_gen0 - * chips as well as new parameters. TCP CC algorithm is not supported. + * chips as well as new parameters. TCP CC algorithm is not + * supported. */ #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN1 (UINT32_C(0x1) << 1) /* @@ -67816,21 +75407,29 @@ typedef struct creq_query_func_resp_sb { * reduce_init_en, reduce_init_cong_free_rtts_th, random_no_red_en, * actual_cr_shift_correction_en, quota_period_adjust_en */ - #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN1_EXT (UINT32_C(0x2) << 1) - #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_LAST CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN1_EXT + #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN1_EXT (UINT32_C(0x2) << 1) + /* + * Enhances cc_gen1_ext support, to include support for DCN/SARA. + * Enables query and modification of Queue level table attributes, + * which are used by the hardware to determine the QP's flow rate + * based on congestion level and thereby reduce RoCE packet drop + * due to network congestion. + */ + #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN2 (UINT32_C(0x3) << 1) + #define CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_LAST CREQ_QUERY_FUNC_RESP_SB_CC_GENERATION_CC_GEN2 /* * Support for the extended RoCE statistics is available. These * statistics are queried via the `query_roce_stats_ext` command * and are enabled on a per-QP basis via `create_qp`. */ - #define CREQ_QUERY_FUNC_RESP_SB_EXT_STATS UINT32_C(0x10) + #define CREQ_QUERY_FUNC_RESP_SB_EXT_STATS UINT32_C(0x10) /* * Support for both allocating and registering a new MR via the * `register_mr` command is available. With this feature the * `allocate_mrw` command does not have to be called before * registering. */ - #define CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC UINT32_C(0x20) + #define CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC UINT32_C(0x20) /* * Support for optimized transmit path to lower latency for WQEs * with inline data. @@ -67841,13 +75440,40 @@ typedef struct creq_query_func_resp_sb { * the following CQE types: * RES_UD, RES_RAWETH_QP1, RES_UD_CFA */ - #define CREQ_QUERY_FUNC_RESP_SB_CQE_V2 UINT32_C(0x80) + #define CREQ_QUERY_FUNC_RESP_SB_CQE_V2 UINT32_C(0x80) /* Support for ping pong push mode is available. */ #define CREQ_QUERY_FUNC_RESP_SB_PINGPONG_PUSH_MODE UINT32_C(0x100) /* Support for hardware requester retransmission is enabled. */ - #define CREQ_QUERY_FUNC_RESP_SB_HW_REQUESTER_RETX_ENABLED UINT32_C(0x200) + #define CREQ_QUERY_FUNC_RESP_SB_HW_REQUESTER_RETX_ENABLED UINT32_C(0x200) /* Support for hardware responder retransmission is enabled. */ - #define CREQ_QUERY_FUNC_RESP_SB_HW_RESPONDER_RETX_ENABLED UINT32_C(0x400) + #define CREQ_QUERY_FUNC_RESP_SB_HW_RESPONDER_RETX_ENABLED UINT32_C(0x400) + /* Support for link aggregation is enabled. */ + #define CREQ_QUERY_FUNC_RESP_SB_LINK_AGGR_SUPPORTED UINT32_C(0x800) + /* link_aggr_supported is valid. */ + #define CREQ_QUERY_FUNC_RESP_SB_LINK_AGGR_SUPPORTED_VALID UINT32_C(0x1000) + /* + * Support for pseudo static QP allocation is enabled. + * This feature enables the following capabilities: + * - QP context ID space is pseudo-static partitioned across PFs. + * - An application can use a predetermined + * QP context ID assignment scheme for specific operations. + * - For 2-port adapters, the application can migrate the QP context + * ID range across PFs, using the `orchestrate_qid_migration` HWRM, + * during network events such as Link Down. + */ + #define CREQ_QUERY_FUNC_RESP_SB_PSEUDO_STATIC_QP_ALLOC_SUPPORTED UINT32_C(0x2000) + /* + * Support for Express Mode is enabled. + * For Express mode, the QP resources (SQ/RQ) are allocated in + * on-chip queue memory. The host driver should not allocate memory + * for these queue structures. + */ + #define CREQ_QUERY_FUNC_RESP_SB_EXPRESS_MODE_SUPPORTED UINT32_C(0x4000) + /* + * IRRQ/ORRQ and MSN Table structures are allocated in internal + * queue memory. + */ + #define CREQ_QUERY_FUNC_RESP_SB_INTERNAL_QUEUE_MEMORY UINT32_C(0x8000) /* Max CQs supported. */ uint32_t max_cq; /* Max CQEs per CQ supported. */ @@ -67855,15 +75481,19 @@ typedef struct creq_query_func_resp_sb { /* Max PDs supported. */ uint32_t max_pd; /* - * Max SGEs per QP WQE supported. On chips with variable-size WQE support, - * this field is applicable only for the backward compatible mode. + * Max SGEs per QP WQE supported. On chips with variable-size WQE + * support, this field is applicable only for the backward compatible + * mode. */ uint8_t max_sge; /* Max SGEs per SRQ WQE supported. */ uint8_t max_srq_sge; /* Max outstanding RDMA read & atomic supported. */ uint8_t max_qp_rd_atom; - /* Max outstanding RDMA read & atomic that can be sent from an initiator. */ + /* + * Max outstanding RDMA read & atomic that can be sent from an + * initiator. + */ uint8_t max_qp_init_rd_atom; /* Max MRs supported. */ uint32_t max_mr; @@ -67893,21 +75523,117 @@ typedef struct creq_query_func_resp_sb { /* Max GIDs supported. */ uint32_t max_gid; /* - * An array of 48 8-bit values to specify allocation multiplier for TQM host buffer regions. - * Each region occupies 16 MB of TQM PBL address space: 0x00000000, 0x01000000, 0x02000000, etc. - * The host needs to allocate (<Number of QPs>*multiplier, rounded up to page size) of physical memory for non-zero slots - * and map the pages to the corresponding 16MB regions. - * Typically there are total 3 non-zero values in this array, their values are 16, 16, 12. - * Cu+ will only populate up to index 11. SR may populate up to index 47. + * An array of 48 8-bit values to specify allocation multiplier for TQM + * host buffer regions. Each region occupies 16 MB of TQM PBL address + * space: 0x00000000, 0x01000000, 0x02000000, etc. + * The host needs to allocate (<Number of QPs>*multiplier, rounded up + * to page size) of physical memory for non-zero slots and map the + * pages to the corresponding 16MB regions. Typically there are total + * 3 non-zero values in this array, their values are 16, 16, 12. + * Cu+ will only populate up to index 11. SR may populate up to + * index 47. */ uint32_t tqm_alloc_reqs[12]; /* Max Doorbell page indices supported. */ uint32_t max_dpi; /* Max SGEs per QP WQE supported in the variable-size WQE mode. */ uint8_t max_sge_var_wqe; - uint8_t reserved_8; + /* Device capability extended flags. */ + uint8_t dev_cap_ext_flags; + /* RDMA Atomic operations are not supported. */ + #define CREQ_QUERY_FUNC_RESP_SB_ATOMIC_OPS_NOT_SUPPORTED UINT32_C(0x1) + /* Support driver version registration. */ + #define CREQ_QUERY_FUNC_RESP_SB_DRV_VERSION_RGTR_SUPPORTED UINT32_C(0x2) + /* Support for batch allocation of QPs is enabled. */ + #define CREQ_QUERY_FUNC_RESP_SB_CREATE_QP_BATCH_SUPPORTED UINT32_C(0x4) + /* Support for batch deletion of QPs is enabled. */ + #define CREQ_QUERY_FUNC_RESP_SB_DESTROY_QP_BATCH_SUPPORTED UINT32_C(0x8) + /* + * Support for extended RoCE statistics context + * with periodic DMA is enabled. The statistics contexts + * are allocated via `allocate_roce_stats_ext_ctx` + * and deallocated via `deallocate_roce_stats_ext_ctx`. + * These contexts are assigned on a per-QP, per-group of QPs + * or per-function basis via `create_qp`, `create_qp_batch` + * or `modify_qp`command. + * In addition to periodic DMA to a host address, + * these statistics can be queried via `query_roce_stats_ext_v2`. + */ + #define CREQ_QUERY_FUNC_RESP_SB_ROCE_STATS_EXT_CTX_SUPPORTED UINT32_C(0x10) + /* + * Support for the srq_sge field in the create_srq command is + * enabled. + */ + #define CREQ_QUERY_FUNC_RESP_SB_CREATE_SRQ_SGE_SUPPORTED UINT32_C(0x20) + /* Support for fixed size SQ wqe (128B) is disabled. */ + #define CREQ_QUERY_FUNC_RESP_SB_FIXED_SIZE_WQE_DISABLED UINT32_C(0x40) + /* Support for DCN (Drop Congestion Notification) is enabled. */ + #define CREQ_QUERY_FUNC_RESP_SB_DCN_SUPPORTED UINT32_C(0x80) /* Max inline data supported in the variable-size WQE mode. */ uint16_t max_inline_data_var_wqe; + /* + * starting xid of the predetermined assignment scheme supported + * by the pseudo static allocation feature. Note that for a PF, + * the start_qid is itself pseudo_static, and can change when the QP + * context id range is migrated by the driver using the + * cmdq_orchestrate_qid_migration. The supported QP count is + * available in the `max_qp` field of `cmdq_query_func`. + */ + uint32_t start_qid; + /* + * Max number of MSN table entries supported for devices that support + * the `internal_queue_memory` feature. + */ + uint8_t max_msn_table_size; + /* reserved8_1 is 8 b */ + uint8_t reserved8_1; + /* Device capability extended flags_2 */ + uint16_t dev_cap_ext_flags_2; + /* Firmware support for optimizing Modify QP operation */ + #define CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED UINT32_C(0x1) + /* + * Device supports changing UDP source port of RoCEv2 packets using + * WQE. + */ + #define CREQ_QUERY_FUNC_RESP_SB_CHANGE_UDP_SRC_PORT_WQE_SUPPORTED UINT32_C(0x2) + /* Device supports CQ Coalescing. */ + #define CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED UINT32_C(0x4) + /* + * Device allows a memory region to be designated as + * relaxed-ordering enabled or disabled. + */ + #define CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED UINT32_C(0x8) + /* The type of lookup table used for requester retransmission. */ + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK UINT32_C(0x30) + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_SFT 4 + /* Requester Retransmission uses a PSN table in host memory. */ + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_PSN_TABLE (UINT32_C(0x0) << 4) + /* Requester Retransmission uses an MSN table in host memory. */ + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE (UINT32_C(0x1) << 4) + /* + * Requester Retransmission uses an MSN table in Device Internal + * Queue Memory. + */ + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE (UINT32_C(0x2) << 4) + #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_LAST CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE + /* + * Max number of 16B IQM memory slots supported by SQ or RQ + * when QP is in express mode. + * This field is only valid for express mode QPs. + */ + uint16_t max_xp_qp_size; + /* + * Max number of QPs that can be created in one `create_qp_batch` + * command. + */ + uint16_t create_qp_batch_size; + /* + * Max number of QPs that can be destroyed in one `destroy_qp_batch` + * command. + */ + uint16_t destroy_qp_batch_size; + uint16_t reserved16; + uint64_t reserved64; } creq_query_func_resp_sb_t, *pcreq_query_func_resp_sb_t; /********************** @@ -67943,15 +75669,34 @@ typedef struct cmdq_set_func_resources { uint8_t reserved8; /* Host address of the response. */ uint64_t resp_addr; - /* Number of QPs. It is the responsibility of the host to first extend the existing PBL with new addresses to pages to handle the adjustment. Must be greater or equal to current. */ + /* + * Number of QPs. It is the responsibility of the host to first extend + * the existing PBL with new addresses to pages to handle the + * adjustment. Must be greater or equal to current. + */ uint32_t number_of_qp; - /* Number of MRWs. It is the responsibility of the host to first extend the existing PBL with new addresses to pages to handle the adjustment. Must be greater or equal to current. */ + /* + * Number of MRWs. It is the responsibility of the host to first extend + * the existing PBL with new addresses to pages to handle the + * adjustment. Must be greater or equal to current. + */ uint32_t number_of_mrw; - /* Number of SRQs. It is the responsibility of the host to first extend the existing PBL with new addresses to pages to handle the adjustment. Must be greater or equal to current. */ + /* + * Number of SRQs. It is the responsibility of the host to first extend + * the existing PBL with new addresses to pages to handle the + * adjustment. Must be greater or equal to current. + */ uint32_t number_of_srq; - /* Number of CQs. It is the responsibility of the host to first extend the existing PBL with new addresses to pages to handle the adjustment. Must be greater or equal to current. */ + /* + * Number of CQs. It is the responsibility of the host to first extend + * the existing PBL with new addresses to pages to handle the + * adjustment. Must be greater or equal to current. + */ uint32_t number_of_cq; - /* Number of QPs per VF. */ + /* + * Number of QPs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_qp_per_vf; /* * If the MR/AV split reservation flag is not set, then this field @@ -67966,13 +75711,25 @@ typedef struct cmdq_set_func_resources { * `max_av_per_vf`. The granularity of these values is defined by * the `mrav_num_entries_unit` field returned by the * `backing_store_qcaps` command. + * + * This field must be set to zero when the flag, l2_vf_resource_mgmt, + * is set and RoCE SRIOV is enabled. */ uint32_t max_mrw_per_vf; - /* Number of SRQs per VF. */ + /* + * Number of SRQs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_srq_per_vf; - /* Number of CQs per VF. */ + /* + * Number of CQs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_cq_per_vf; - /* Number of GIDs per VF. */ + /* + * Number of GIDs per VF. This field must be set to zero when the flag, + * l2_vf_resource_mgmt, is set and RoCE SRIOV is enabled. + */ uint32_t max_gid_per_vf; /* Statistics context index for this function. */ uint32_t stat_ctx_id; @@ -68086,7 +75843,10 @@ typedef struct creq_stop_func_resp { typedef struct cmdq_read_context { /* Command opcode. */ uint8_t opcode; - /* Read the current state of any internal resource context. Can only be issued from a PF. */ + /* + * Read the current state of any internal resource context. Can only + * be issued from a PF. + */ #define CMDQ_READ_CONTEXT_OPCODE_READ_CONTEXT UINT32_C(0x85) #define CMDQ_READ_CONTEXT_OPCODE_LAST CMDQ_READ_CONTEXT_OPCODE_READ_CONTEXT /* Size of the command in 16-byte units. */ @@ -68100,23 +75860,33 @@ typedef struct cmdq_read_context { uint8_t reserved8; /* Host address of the response. */ uint64_t resp_addr; - uint32_t type_xid; /* Context ID */ - #define CMDQ_READ_CONTEXT_XID_MASK UINT32_C(0xffffff) - #define CMDQ_READ_CONTEXT_XID_SFT 0 + uint32_t xid; /* Context type */ - #define CMDQ_READ_CONTEXT_TYPE_MASK UINT32_C(0xff000000) - #define CMDQ_READ_CONTEXT_TYPE_SFT 24 - /* Read QPC. The context (448 bytes) goes to resp_addr (as is, without a header), and resp_size should be set to 28 (448/16) */ - #define CMDQ_READ_CONTEXT_TYPE_QPC (UINT32_C(0x0) << 24) - /* Read CQ. The context (64 bytes) goes to resp_addr (as is, without a header), and resp_size should be set to 4 (64/16) */ - #define CMDQ_READ_CONTEXT_TYPE_CQ (UINT32_C(0x1) << 24) - /* Read MRW. The context (128 bytes) goes to resp_addr (as is, without a header), and resp_size should be set to 8 (128/16) */ - #define CMDQ_READ_CONTEXT_TYPE_MRW (UINT32_C(0x2) << 24) - /* Read SRQ. The context (64 bytes) goes to resp_addr (as is, without a header), and resp_size should be set to 4 (64/16) */ - #define CMDQ_READ_CONTEXT_TYPE_SRQ (UINT32_C(0x3) << 24) - #define CMDQ_READ_CONTEXT_TYPE_LAST CMDQ_READ_CONTEXT_TYPE_SRQ - uint32_t unused_0; + uint8_t type; + /* + * Read QPC. The context (448 bytes) goes to resp_addr (as is, + * without a header), and resp_size should be set to 28 + * (448/16). + */ + #define CMDQ_READ_CONTEXT_TYPE_QPC UINT32_C(0x0) + /* + * Read CQ. The context (64 bytes) goes to resp_addr (as is, + * without a header), and resp_size should be set to 4 (64/16) + */ + #define CMDQ_READ_CONTEXT_TYPE_CQ UINT32_C(0x1) + /* + * Read MRW. The context (128 bytes) goes to resp_addr (as is, + * without a header), and resp_size should be set to 8 (128/16) + */ + #define CMDQ_READ_CONTEXT_TYPE_MRW UINT32_C(0x2) + /* + * Read SRQ. The context (64 bytes) goes to resp_addr (as is, + * without a header), and resp_size should be set to 4 (64/16) + */ + #define CMDQ_READ_CONTEXT_TYPE_SRQ UINT32_C(0x3) + #define CMDQ_READ_CONTEXT_TYPE_LAST CMDQ_READ_CONTEXT_TYPE_SRQ + uint8_t unused_0[3]; } cmdq_read_context_t, *pcmdq_read_context_t; /* creq_read_context (size:128b/16B) */ @@ -68149,7 +75919,10 @@ typedef struct creq_read_context { #define CREQ_READ_CONTEXT_V UINT32_C(0x1) /* Event or command opcode. */ uint8_t event; - /* Read the current state of any internal resource context. Can only be issued from a PF. */ + /* + * Read the current state of any internal resource context. Can only + * be issued from a PF. + */ #define CREQ_READ_CONTEXT_EVENT_READ_CONTEXT UINT32_C(0x85) #define CREQ_READ_CONTEXT_EVENT_LAST CREQ_READ_CONTEXT_EVENT_READ_CONTEXT uint16_t reserved16; @@ -68322,7 +76095,10 @@ typedef struct creq_query_roce_cc_resp_sb { /* IP TOS ECN. */ #define CREQ_QUERY_ROCE_CC_RESP_SB_TOS_ECN_MASK UINT32_C(0x3) #define CREQ_QUERY_ROCE_CC_RESP_SB_TOS_ECN_SFT 0 - /* IP TOS DSCP. */ + /* + * IP TOS DSCP. When multi-lossless queue feature is enabled, + * query applies only to the default traffic class (1). + */ #define CREQ_QUERY_ROCE_CC_RESP_SB_TOS_DSCP_MASK UINT32_C(0xfc) #define CREQ_QUERY_ROCE_CC_RESP_SB_TOS_DSCP_SFT 2 /* Congestion Probability averaging factor. */ @@ -68470,7 +76246,10 @@ typedef struct creq_query_roce_cc_resp_sb_tlv { /* IP TOS ECN. */ #define CREQ_QUERY_ROCE_CC_RESP_SB_TLV_TOS_ECN_MASK UINT32_C(0x3) #define CREQ_QUERY_ROCE_CC_RESP_SB_TLV_TOS_ECN_SFT 0 - /* IP TOS DSCP. */ + /* + * IP TOS DSCP. When multi-lossless queue feature is enabled, + * query applies only to the default traffic class (1). + */ #define CREQ_QUERY_ROCE_CC_RESP_SB_TLV_TOS_DSCP_MASK UINT32_C(0xfc) #define CREQ_QUERY_ROCE_CC_RESP_SB_TLV_TOS_DSCP_SFT 2 /* Congestion Probability averaging factor. */ @@ -68586,9 +76365,15 @@ typedef struct creq_query_roce_cc_gen1_resp_sb_tlv { uint64_t reserved64; /* High order bits of inactivity threshold. */ uint16_t inactivity_th_hi; - /* The number of uS between generation of CNPs when cc_mode is probabilistic marking. */ + /* + * The number of uS between generation of CNPs when cc_mode is + * probabilistic marking. + */ uint16_t min_time_between_cnps; - /* The starting value of congestion probability. Input range is 0 - 1023. */ + /* + * The starting value of congestion probability. Input range + * is 0 - 1023. + */ uint16_t init_cp; /* * In tr_update_mode 0, Target Rate (TR) is updated to @@ -68692,8 +76477,9 @@ typedef struct creq_query_roce_cc_gen1_resp_sb_tlv { uint8_t tr_prob_factor; /* * Threshold to ensure fairness between requester and responder. - * If CR is less than the fairness threshold and a quota period has passed - * priority will be given to the path that did not last transfer data. + * If CR is less than the fairness threshold and a quota period has + * passed priority will be given to the path that did not last + * transfer data. */ uint16_t fairness_cr_th; /* Log based rate reduction divider. */ @@ -68714,9 +76500,15 @@ typedef struct creq_query_roce_cc_gen1_resp_sb_tlv { * updating CP to track CR. */ uint16_t cp_exp_update_th; - /* The threshold on congestion free RTTs above which AI can increase to 16. */ + /* + * The threshold on congestion free RTTs above which AI can increase + * to 16. + */ uint16_t high_exp_ai_rtts_th1; - /* The threshold on congestion free RTTs above which AI can increase to 32. */ + /* + * The threshold on congestion free RTTs above which AI can increase + * to 32. + */ uint16_t high_exp_ai_rtts_th2; /* * The number of congestion free RTTs above which @@ -68751,19 +76543,101 @@ typedef struct creq_query_roce_cc_gen1_resp_sb_tlv { */ uint8_t reduce_init_en; /* - * Minimum threshold value for number of congestion free RTTs before reducing - * to init values for CR, TR, and CP when reduce_init_en is enabled. + * Minimum threshold value for number of congestion free RTTs before + * reducing to init values for CR, TR, and CP when reduce_init_en is + * enabled. */ uint16_t reduce_init_cong_free_rtts_th; /* Enables random no reduction of CR. */ uint8_t random_no_red_en; - /* Enables coarse correction to actual CR when actual RTT is longer than nominal. */ + /* + * Enables coarse correction to actual CR when actual RTT is longer + * than nominal. + */ uint8_t actual_cr_shift_correction_en; /* Enables adjustment to refill quota. */ uint8_t quota_period_adjust_en; uint8_t reserved[5]; } creq_query_roce_cc_gen1_resp_sb_tlv_t, *pcreq_query_roce_cc_gen1_resp_sb_tlv_t; +/* creq_query_roce_cc_gen2_resp_sb_tlv (size:512b/64B) */ + +typedef struct creq_query_roce_cc_gen2_resp_sb_tlv { + /* + * The command discriminator is used to differentiate between various + * types of HWRM messages. This includes legacy HWRM and RoCE slowpath + * command messages as well as newer TLV encapsulated HWRM commands. + * + * For TLV encapsulated messages this field must be 0x8000. + */ + uint16_t cmd_discr; + uint8_t reserved_8b; + uint8_t tlv_flags; + /* + * Indicates the presence of additional TLV encapsulated data + * follows this TLV. + */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_MORE UINT32_C(0x1) + /* Last TLV in a sequence of TLVs. */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_MORE_LAST UINT32_C(0x0) + /* More TLVs follow this TLV. */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_MORE_NOT_LAST UINT32_C(0x1) + /* + * When an HWRM receiver detects a TLV type that it does not + * support with the TLV required flag set, the receiver must + * reject the HWRM message with an error code indicating an + * unsupported TLV type. + */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_REQUIRED UINT32_C(0x2) + /* No */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_REQUIRED_NO (UINT32_C(0x0) << 1) + /* Yes */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_REQUIRED_YES (UINT32_C(0x1) << 1) + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_REQUIRED_LAST CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_TLV_FLAGS_REQUIRED_YES + /* + * This field defines the TLV type value which is divided into + * two ranges to differentiate between global and local TLV types. + * Global TLV types must be unique across all defined TLV types. + * Local TLV types are valid only for extensions to a given + * HWRM message and may be repeated across different HWRM message + * types. There is a direct correlation of each HWRM message type + * to a single global TLV type value. + * + * Global TLV range: `0 - (63k-1)` + * + * Local TLV range: `63k - (64k-1)` + */ + uint16_t tlv_type; + /* + * Length of the message data encapsulated by this TLV in bytes. + * This length does not include the size of the TLV header itself + * and it must be an integer multiple of 8B. + */ + uint16_t length; + uint64_t reserved64; + /* + * DCN queue level threshold values associated with DCN queue + * level table indices 0 to 7. + */ + uint16_t dcn_qlevel_tbl_thr[8]; + /* + * DCN queue level table action values. + * Returns CR, INC_CNP, UPD_IMM & TR fields associated with + * DCN queue level table indices 0 to 7. + */ + uint32_t dcn_qlevel_tbl_act[8]; + /* DCN queue level current rate. */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_CR_MASK UINT32_C(0x3fff) + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_CR_SFT 0 + /* DCN queue level increment CNP count. */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_INC_CNP UINT32_C(0x4000) + /* DCN queue level update CR and TR immediately. */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_UPD_IMM UINT32_C(0x8000) + /* DCN queue level target rate */ + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_TR_MASK UINT32_C(0x3fff0000) + #define CREQ_QUERY_ROCE_CC_GEN2_RESP_SB_TLV_DCN_QLEVEL_TBL_ACT_TR_SFT 16 +} creq_query_roce_cc_gen2_resp_sb_tlv_t, *pcreq_query_roce_cc_gen2_resp_sb_tlv_t; + /*********************** * cmdq_modify_roce_cc * ***********************/ @@ -68848,7 +76722,10 @@ typedef struct cmdq_modify_roce_cc { /* IP TOS ECN. Valid values are 1 or 2 when ECN is enabled. */ #define CMDQ_MODIFY_ROCE_CC_TOS_ECN_MASK UINT32_C(0x3) #define CMDQ_MODIFY_ROCE_CC_TOS_ECN_SFT 0 - /* IP TOS DSCP. */ + /* + * IP TOS DSCP. When multi-lossless queue feature is enabled, + * update applies only to the default traffic class (1). + */ #define CMDQ_MODIFY_ROCE_CC_TOS_DSCP_MASK UINT32_C(0xfc) #define CMDQ_MODIFY_ROCE_CC_TOS_DSCP_SFT 2 uint8_t alt_vlan_pcp; @@ -68967,7 +76844,10 @@ typedef struct cmdq_modify_roce_cc_tlv { * and it must be an integer multiple of 8B. */ uint16_t length; - /* Size of the tlv encapsulated command, including all tlvs and extension data in 16-byte units. */ + /* + * Size of the tlv encapsulated command, including all tlvs and + * extension data in 16-byte units. + */ uint8_t total_size; uint8_t reserved56[7]; /* Command opcode. */ @@ -69046,7 +76926,10 @@ typedef struct cmdq_modify_roce_cc_tlv { /* IP TOS ECN. Valid values are 1 or 2 when ECN is enabled. */ #define CMDQ_MODIFY_ROCE_CC_TLV_TOS_ECN_MASK UINT32_C(0x3) #define CMDQ_MODIFY_ROCE_CC_TLV_TOS_ECN_SFT 0 - /* IP TOS DSCP. */ + /* + * IP TOS DSCP. When multi-lossless queue feature is enabled, + * update applies only to the default traffic class (1). + */ #define CMDQ_MODIFY_ROCE_CC_TLV_TOS_DSCP_MASK UINT32_C(0xfc) #define CMDQ_MODIFY_ROCE_CC_TLV_TOS_DSCP_SFT 2 uint8_t alt_vlan_pcp; @@ -69165,7 +77048,10 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { uint64_t reserved64; /* Modify mask signifies the field that is requesting the change. */ uint64_t modify_mask; - /* Update the number of uS between generation of CNPs for probabilistic marking mode. */ + /* + * Update the number of uS between generation of CNPs for + * probabilistic marking mode. + */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_MIN_TIME_BETWEEN_CNPS UINT32_C(0x1) /* * Update starting value of Congestion Probability (CP). @@ -69211,7 +77097,10 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_RTT_JITTER_EN UINT32_C(0x8000) /* Update number of bytes per usec. */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_LINK_BYTES_PER_USEC UINT32_C(0x10000) - /* Update threshold used to reset QPC CC state to its initial state. */ + /* + * Update threshold used to reset QPC CC state to its initial + * state. + */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_RESET_CC_CR_TH UINT32_C(0x20000) /* Update number of valid lsbits in CR and TR */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_CR_WIDTH UINT32_C(0x40000) @@ -69299,7 +77188,10 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_CC_ACK_BYTES UINT32_C(0x4000000000)L /* Update enable of reduction of CR, TR, and CP to init values. */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_REDUCE_INIT_EN UINT32_C(0x8000000000)L - /* Update threshold used for reduction of CR, TR, and CP to init values. */ + /* + * Update threshold used for reduction of CR, TR, and CP to init + * values. + */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_REDUCE_INIT_CONG_FREE_RTTS_TH UINT32_C(0x10000000000)L /* Update enable of random no reduction of CR. */ #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_RANDOM_NO_RED_EN UINT32_C(0x20000000000)L @@ -69309,9 +77201,15 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { #define CMDQ_MODIFY_ROCE_CC_GEN1_TLV_MODIFY_MASK_QUOTA_PERIOD_ADJUST_EN UINT32_C(0x80000000000)L /* High order bits of inactivity threshold. */ uint16_t inactivity_th_hi; - /* The number of uS between generation of CNPs when cc_mode is probabilistic marking. */ + /* + * The number of uS between generation of CNPs when cc_mode is + * probabilistic marking. + */ uint16_t min_time_between_cnps; - /* The starting value of congestion probability. Input range is 0 - 1023. */ + /* + * The starting value of congestion probability. Input range + * is 0 - 1023. + */ uint16_t init_cp; /* * In tr_update_mode 0, Target Rate (TR) is updated to @@ -69415,8 +77313,9 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { uint8_t tr_prob_factor; /* * Threshold to ensure fairness between requester and responder. - * If CR is less than the fairness threshold and a quota period has passed - * priority will be given to the path that did not last transfer data. + * If CR is less than the fairness threshold and a quota period has + * passed priority will be given to the path that did not last + * transfer data. */ uint16_t fairness_cr_th; /* Log based rate reduction divider. */ @@ -69437,9 +77336,15 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { * updating CP to track CR. */ uint16_t cp_exp_update_th; - /* The threshold on congestion free RTTs above which AI can increase to 16. */ + /* + * The threshold on congestion free RTTs above which AI can increase + * to 16. + */ uint16_t high_exp_ai_rtts_th1; - /* The threshold on congestion free RTTs above which AI can increase to 32. */ + /* + * The threshold on congestion free RTTs above which AI can increase + * to 32. + */ uint16_t high_exp_ai_rtts_th2; /* * The number of congestion free RTTs above which @@ -69474,19 +77379,122 @@ typedef struct cmdq_modify_roce_cc_gen1_tlv { */ uint8_t reduce_init_en; /* - * Minimum threshold value for number of congestion free RTTs before reducing - * to init values for CR, TR, and CP when reduce_init_en is enabled. + * Minimum threshold value for number of congestion free RTTs before + * reducing to init values for CR, TR, and CP when reduce_init_en is + * enabled. */ uint16_t reduce_init_cong_free_rtts_th; /* Enables random no reduction of CR. */ uint8_t random_no_red_en; - /* Enables coarse correction to actual CR when actual RTT is longer than nominal. */ + /* + * Enables coarse correction to actual CR when actual RTT is longer + * than nominal. + */ uint8_t actual_cr_shift_correction_en; /* Enables adjustment to refill quota. */ uint8_t quota_period_adjust_en; uint8_t reserved[5]; } cmdq_modify_roce_cc_gen1_tlv_t, *pcmdq_modify_roce_cc_gen1_tlv_t; +/* cmdq_modify_roce_cc_gen2_tlv (size:256b/32B) */ + +typedef struct cmdq_modify_roce_cc_gen2_tlv { + /* + * The command discriminator is used to differentiate between various + * types of HWRM messages. This includes legacy HWRM and RoCE slowpath + * command messages as well as newer TLV encapsulated HWRM commands. + * + * For TLV encapsulated messages this field must be 0x8000. + */ + uint16_t cmd_discr; + uint8_t reserved_8b; + uint8_t tlv_flags; + /* + * Indicates the presence of additional TLV encapsulated data + * follows this TLV. + */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_MORE UINT32_C(0x1) + /* Last TLV in a sequence of TLVs. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_MORE_LAST UINT32_C(0x0) + /* More TLVs follow this TLV. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_MORE_NOT_LAST UINT32_C(0x1) + /* + * When an HWRM receiver detects a TLV type that it does not + * support with the TLV required flag set, the receiver must + * reject the HWRM message with an error code indicating an + * unsupported TLV type. + */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_REQUIRED UINT32_C(0x2) + /* No */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_REQUIRED_NO (UINT32_C(0x0) << 1) + /* Yes */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_REQUIRED_YES (UINT32_C(0x1) << 1) + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_REQUIRED_LAST CMDQ_MODIFY_ROCE_CC_GEN2_TLV_TLV_FLAGS_REQUIRED_YES + /* + * This field defines the TLV type value which is divided into + * two ranges to differentiate between global and local TLV types. + * Global TLV types must be unique across all defined TLV types. + * Local TLV types are valid only for extensions to a given + * HWRM message and may be repeated across different HWRM message + * types. There is a direct correlation of each HWRM message type + * to a single global TLV type value. + * + * Global TLV range: `0 - (63k-1)` + * + * Local TLV range: `63k - (64k-1)` + */ + uint16_t tlv_type; + /* + * Length of the message data encapsulated by this TLV in bytes. + * This length does not include the size of the TLV header itself + * and it must be an integer multiple of 8B. + */ + uint16_t length; + uint64_t reserved64; + /* Modify mask signifies the field that is requesting the change. */ + uint64_t modify_mask; + /* + * Modify the specific DCN queue level table index data. + * This must be set, to select the table index that needs an + * update. + */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_IDX UINT32_C(0x1) + /* Modify the DCN queue level threshold. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_THR UINT32_C(0x2) + /* Modify DCN queue level current rate. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_CR UINT32_C(0x4) + /* Modify DCN queue level increment CNP count. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_INC_CNP UINT32_C(0x8) + /* Modify DCN queue level update current & target rate immediately. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_UPD_IMM UINT32_C(0x10) + /* Modify DCN queue level target rate. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_MODIFY_MASK_DCN_QLEVEL_TBL_TR UINT32_C(0x20) + /* DCN queue level table index. Valid values are from 0 to 7. */ + uint8_t dcn_qlevel_tbl_idx; + uint8_t reserved8; + /* + * DCN queue level threshold value associated with a DCN queue + * level table index. + */ + uint16_t dcn_qlevel_tbl_thr; + /* + * DCN queue level table action. + * Updates CR, INC_CNP, UPD_IMM & TR fields associated with the + * DCN queue level table index. + */ + uint32_t dcn_qlevel_tbl_act; + /* DCN queue level current rate. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_CR_MASK UINT32_C(0x3fff) + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_CR_SFT 0 + /* DCN queue level increment CNP count. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_INC_CNP UINT32_C(0x4000) + /* DCN queue level update CR and TR immediately. */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_UPD_IMM UINT32_C(0x8000) + /* DCN queue level target rate */ + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_TR_MASK UINT32_C(0x3fff0000) + #define CMDQ_MODIFY_ROCE_CC_GEN2_TLV_DCN_QLEVEL_TBL_ACT_TR_SFT 16 +} cmdq_modify_roce_cc_gen2_tlv_t, *pcmdq_modify_roce_cc_gen2_tlv_t; + /* creq_modify_roce_cc_resp (size:128b/16B) */ typedef struct creq_modify_roce_cc_resp { @@ -69632,7 +77640,10 @@ typedef struct creq_set_link_aggr_mode_resources_resp { typedef struct cmdq_vf_backchannel_request { /* Command opcode. */ uint8_t opcode; - /* Send a request from VF to pass a command to the PF. VF HSI is suspended until the PF returns the response */ + /* + * Send a request from VF to pass a command to the PF. VF HSI is + * suspended until the PF returns the response. + */ #define CMDQ_VF_BACKCHANNEL_REQUEST_OPCODE_VF_BACKCHANNEL_REQUEST UINT32_C(0x86) #define CMDQ_VF_BACKCHANNEL_REQUEST_OPCODE_LAST CMDQ_VF_BACKCHANNEL_REQUEST_OPCODE_VF_BACKCHANNEL_REQUEST /* Size of the command in 16-byte units. */ @@ -69648,7 +77659,10 @@ typedef struct cmdq_vf_backchannel_request { uint64_t resp_addr; /* Address of command request structure in VF space */ uint64_t command_addr; - /* Command request length (up to 4K). An optional address of the extended response buffer should be provided in the request */ + /* + * Command request length (up to 4K). An optional address of the extended + * response buffer should be provided in the request. + */ uint16_t command_length; uint8_t unused_0[6]; } cmdq_vf_backchannel_request_t, *pcmdq_vf_backchannel_request_t; @@ -69659,7 +77673,10 @@ typedef struct cmdq_vf_backchannel_request { typedef struct cmdq_read_vf_memory { /* Command opcode. */ uint8_t opcode; - /* Read VF memory (primarily to get the backchannel request blob). Can only be issued from a PF. */ + /* + * Read VF memory (primarily to get the backchannel request blob). Can + * only be issued from a PF. + */ #define CMDQ_READ_VF_MEMORY_OPCODE_READ_VF_MEMORY UINT32_C(0x87) #define CMDQ_READ_VF_MEMORY_OPCODE_LAST CMDQ_READ_VF_MEMORY_OPCODE_READ_VF_MEMORY /* Size of the command in 16-byte units. */ @@ -69688,7 +77705,11 @@ typedef struct cmdq_read_vf_memory { typedef struct cmdq_complete_vf_request { /* Command opcode. */ uint8_t opcode; - /* Write VF memory (primarily to put the backchannel response blob), and reenable VF HSI (post a CAG completion to it). Can only be issued from a PF. */ + /* + * Write VF memory (primarily to put the backchannel response blob), + * and reenable VF HSI (post a CAG completion to it). Can only be + * issued from a PF. + */ #define CMDQ_COMPLETE_VF_REQUEST_OPCODE_COMPLETE_VF_REQUEST UINT32_C(0x88) #define CMDQ_COMPLETE_VF_REQUEST_OPCODE_LAST CMDQ_COMPLETE_VF_REQUEST_OPCODE_COMPLETE_VF_REQUEST /* Size of the command in 16-byte units. */ @@ -69702,7 +77723,10 @@ typedef struct cmdq_complete_vf_request { uint8_t reserved8; /* Host address of the response. */ uint64_t resp_addr; - /* Optional address of extended response in VF space to write. Length is in resp_size in 16 byte units. */ + /* + * Optional address of extended response in VF space to write. Length is + * in resp_size in 16 byte units. + */ uint64_t addr; /* Completion misc field to VF CREQ */ uint32_t vf_misc; @@ -69716,6 +77740,587 @@ typedef struct cmdq_complete_vf_request { uint32_t unused_1; } cmdq_complete_vf_request_t, *pcmdq_complete_vf_request_t; +/***************************** + * orchestrate_qid_migration * + *****************************/ + + +/* cmdq_orchestrate_qid_migration (size:256b/32B) */ + +typedef struct cmdq_orchestrate_qid_migration { + /* Command opcode. */ + uint8_t opcode; + /* + * This command updates the QP context id ranges on the PF, + * to orchestrate QP context id range migration for devices that + * support the pseudo-static QP allocation feature. + */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_OPCODE_ORCHESTRATE_QID_MIGRATION UINT32_C(0x93) + #define CMDQ_ORCHESTRATE_QID_MIGRATION_OPCODE_LAST CMDQ_ORCHESTRATE_QID_MIGRATION_OPCODE_ORCHESTRATE_QID_MIGRATION + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + uint8_t qid_migration_flags; + /* Flags to orchestrate QP context ID range migration amongst PFs. */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_MASK UINT32_C(0xf) + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_SFT 0 + /* Enable the PF's native QP context ID range. */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_ENABLE_NATIVE_QID_RANGE UINT32_C(0x0) + /* Enable the PF's extended QP context ID range. */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_ENABLE_EXTENDED_QID_RANGE UINT32_C(0x1) + /* Disable the PF's native QP context ID range. */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_DISABLE_NATIVE_QID_RANGE UINT32_C(0x2) + /* Disable the PF's extended QP context ID range. */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_DISABLE_EXTENDED_QID_RANGE UINT32_C(0x3) + #define CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_LAST CMDQ_ORCHESTRATE_QID_MIGRATION_QID_MIGRATION_FLAGS_DISABLE_EXTENDED_QID_RANGE + /* unused4 is 4 b */ + #define CMDQ_ORCHESTRATE_QID_MIGRATION_UNUSED4_MASK UINT32_C(0xf0) + #define CMDQ_ORCHESTRATE_QID_MIGRATION_UNUSED4_SFT 4 + uint8_t reserved56[7]; + /* reserved64 is 64 b */ + uint64_t reserved64; +} cmdq_orchestrate_qid_migration_t, *pcmdq_orchestrate_qid_migration_t; + +/* creq_orchestrate_qid_migration_resp (size:128b/16B) */ + +typedef struct creq_orchestrate_qid_migration_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_TYPE_LAST CREQ_ORCHESTRATE_QID_MIGRATION_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + uint32_t reserved32; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Orchestrate QPID migration command response. */ + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_EVENT_ORCHESTRATE_QID_MIGRATION UINT32_C(0x93) + #define CREQ_ORCHESTRATE_QID_MIGRATION_RESP_EVENT_LAST CREQ_ORCHESTRATE_QID_MIGRATION_RESP_EVENT_ORCHESTRATE_QID_MIGRATION + uint8_t reserved48[6]; +} creq_orchestrate_qid_migration_resp_t, *pcreq_orchestrate_qid_migration_resp_t; + +/******************* + * create_qp_batch * + *******************/ + + +/* cmdq_create_qp_batch (size:384b/48B) */ + +typedef struct cmdq_create_qp_batch { + /* Command opcode. */ + uint8_t opcode; + /* This command allocates a batch of QPs in a sequential range. */ + #define CMDQ_CREATE_QP_BATCH_OPCODE_CREATE_QP_BATCH UINT32_C(0x94) + #define CMDQ_CREATE_QP_BATCH_OPCODE_LAST CMDQ_CREATE_QP_BATCH_OPCODE_CREATE_QP_BATCH + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + /* Starting QP context id to be used for the sequential range. */ + uint32_t start_xid; + /* Count of QPs to be allocated */ + uint32_t count; + /* Size of an individual element of the qp_params_array. */ + uint32_t per_qp_param_size; + uint32_t reserved32; + /* + * Host DMA address of the array of per-QP parameters. + * Per-QP parameters are identical to those of the + * `create_qp` command and specified by the + * `create_qp_batch_data` structure. + */ + uint64_t qp_params_array; + /* reserved64 is 64 b */ + uint64_t reserved64; +} cmdq_create_qp_batch_t, *pcmdq_create_qp_batch_t; + +/* creq_create_qp_batch_resp (size:128b/16B) */ + +typedef struct creq_create_qp_batch_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_CREATE_QP_BATCH_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_CREATE_QP_BATCH_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_CREATE_QP_BATCH_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_CREATE_QP_BATCH_RESP_TYPE_LAST CREQ_CREATE_QP_BATCH_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + uint32_t reserved32; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_CREATE_QP_BATCH_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Create batch QPs command response. */ + #define CREQ_CREATE_QP_BATCH_RESP_EVENT_CREATE_QP_BATCH UINT32_C(0x94) + #define CREQ_CREATE_QP_BATCH_RESP_EVENT_LAST CREQ_CREATE_QP_BATCH_RESP_EVENT_CREATE_QP_BATCH + uint16_t reserved16; + /* Count of QPs successfully created. */ + uint32_t count; +} creq_create_qp_batch_resp_t, *pcreq_create_qp_batch_resp_t; + +/******************** + * destroy_qp_batch * + ********************/ + + +/* cmdq_destroy_qp_batch (size:256b/32B) */ + +typedef struct cmdq_destroy_qp_batch { + /* Command opcode. */ + uint8_t opcode; + /* + * This command deletes the batch of requested count of QPs. + * The starting QP ID can be specified to request a batch deletion + * of a sequential range. + */ + #define CMDQ_DESTROY_QP_BATCH_OPCODE_DESTROY_QP_BATCH UINT32_C(0x95) + #define CMDQ_DESTROY_QP_BATCH_OPCODE_LAST CMDQ_DESTROY_QP_BATCH_OPCODE_DESTROY_QP_BATCH + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + /* Starting QP context id to be used for the sequential range. */ + uint32_t start_xid; + /* + * Count of QPs to be deleted. A value of zero implies all QPs + * are to be deleted. + */ + uint32_t count; + /* reserved64 is 64 b */ + uint64_t reserved64; +} cmdq_destroy_qp_batch_t, *pcmdq_destroy_qp_batch_t; + +/* creq_destroy_qp_batch_resp (size:128b/16B) */ + +typedef struct creq_destroy_qp_batch_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_DESTROY_QP_BATCH_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_DESTROY_QP_BATCH_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_DESTROY_QP_BATCH_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_DESTROY_QP_BATCH_RESP_TYPE_LAST CREQ_DESTROY_QP_BATCH_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + uint32_t reserved32; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_DESTROY_QP_BATCH_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Destroy batch QPs command response. */ + #define CREQ_DESTROY_QP_BATCH_RESP_EVENT_DESTROY_QP_BATCH UINT32_C(0x95) + #define CREQ_DESTROY_QP_BATCH_RESP_EVENT_LAST CREQ_DESTROY_QP_BATCH_RESP_EVENT_DESTROY_QP_BATCH + uint16_t reserved16; + /* Count of QPs successfully destroyed. */ + uint32_t count; +} creq_destroy_qp_batch_resp_t, *pcreq_destroy_qp_batch_resp_t; + +/******************************* + * allocate_roce_stats_ext_ctx * + *******************************/ + + +/* cmdq_allocate_roce_stats_ext_ctx (size:256b/32B) */ + +typedef struct cmdq_allocate_roce_stats_ext_ctx { + /* Command opcode. */ + uint8_t opcode; + /* + * This command allocates an extended RoCE statistics context + * that supports periodic DMA to a host address. The extended + * statistics context id can be assigned by the driver, + * via `create_qp`, `create_qp_batch` or `modify_qp` to a + * specific QP, a subset of QPs or to all QPs of a specific function. + * These statistics can be queried via `query_roce_stats_ext_v2`. + */ + #define CMDQ_ALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_ALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x96) + #define CMDQ_ALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_LAST CMDQ_ALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_ALLOCATE_ROCE_STATS_EXT_CTX + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + /* + * This is the address to be programmed in the statistic block + * by the firmware to support periodic DMA of the statistics. + */ + uint64_t stats_dma_addr; + /* + * The statistic block update period in ms. + * e.g. 250ms, 500ms, 750ms, 1000ms. + * If update_period_ms is 0, then the stats update + * shall be never done and the DMA address shall not be used. + * In this case, the statistics can only be read by + * `query_roce_stats_ext_v2` command. + */ + uint32_t update_period_ms; + /* Steering tag to use for memory transactions. */ + uint16_t steering_tag; + uint16_t reserved16; +} cmdq_allocate_roce_stats_ext_ctx_t, *pcmdq_allocate_roce_stats_ext_ctx_t; + +/* creq_allocate_roce_stats_ext_ctx_resp (size:128b/16B) */ + +typedef struct creq_allocate_roce_stats_ext_ctx_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_LAST CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Extended RoCE statistics context id. */ + uint32_t roce_stats_ext_xid; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Allocate extended RoCE statistics context command response. */ + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_ALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x96) + #define CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_LAST CREQ_ALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_ALLOCATE_ROCE_STATS_EXT_CTX + uint8_t reserved48[6]; +} creq_allocate_roce_stats_ext_ctx_resp_t, *pcreq_allocate_roce_stats_ext_ctx_resp_t; + +/********************************* + * deallocate_roce_stats_ext_ctx * + *********************************/ + + +/* cmdq_deallocate_roce_stats_ext_ctx (size:256b/32B) */ + +typedef struct cmdq_deallocate_roce_stats_ext_ctx { + /* Command opcode. */ + uint8_t opcode; + /* This command deallocates an extended RoCE statistics context. */ + #define CMDQ_DEALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_DEALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x97) + #define CMDQ_DEALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_LAST CMDQ_DEALLOCATE_ROCE_STATS_EXT_CTX_OPCODE_DEALLOCATE_ROCE_STATS_EXT_CTX + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + /* Extended RoCE statistics context id. */ + uint32_t roce_stats_ext_xid; + uint32_t reserved32; + /* reserved64 is 64 b */ + uint64_t reserved64; +} cmdq_deallocate_roce_stats_ext_ctx_t, *pcmdq_deallocate_roce_stats_ext_ctx_t; + +/* creq_deallocate_roce_stats_ext_ctx_resp (size:128b/16B) */ + +typedef struct creq_deallocate_roce_stats_ext_ctx_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_LAST CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Extended RoCE statistics context id. */ + uint32_t roce_stats_ext_xid; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Deallocate extended RoCE statistics context command response. */ + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_DEALLOCATE_ROCE_STATS_EXT_CTX UINT32_C(0x97) + #define CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_LAST CREQ_DEALLOCATE_ROCE_STATS_EXT_CTX_RESP_EVENT_DEALLOCATE_ROCE_STATS_EXT_CTX + uint8_t reserved48[6]; +} creq_deallocate_roce_stats_ext_ctx_resp_t, *pcreq_deallocate_roce_stats_ext_ctx_resp_t; + +/*************************** + * query_roce_stats_ext_v2 * + ***************************/ + + +/* cmdq_query_roce_stats_ext_v2 (size:256b/32B) */ + +typedef struct cmdq_query_roce_stats_ext_v2 { + /* Command opcode. */ + uint8_t opcode; + /* + * Query extended RoCE statistics for devices that support + * `roce_stats_ext_ctx_supported` feature. + */ + #define CMDQ_QUERY_ROCE_STATS_EXT_V2_OPCODE_QUERY_ROCE_STATS_EXT_V2 UINT32_C(0x98) + #define CMDQ_QUERY_ROCE_STATS_EXT_V2_OPCODE_LAST CMDQ_QUERY_ROCE_STATS_EXT_V2_OPCODE_QUERY_ROCE_STATS_EXT_V2 + /* Size of the command in 16-byte units. */ + uint8_t cmd_size; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t reserved8; + /* Host address of the response. */ + uint64_t resp_addr; + /* Extended RoCE statistics context id. */ + uint32_t roce_stats_ext_xid; + uint32_t reserved32; + /* reserved64 is 64 b */ + uint64_t reserved64; +} cmdq_query_roce_stats_ext_v2_t, *pcmdq_query_roce_stats_ext_v2_t; + +/* creq_query_roce_stats_ext_v2_resp (size:128b/16B) */ + +typedef struct creq_query_roce_stats_ext_v2_resp { + uint8_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B + * records. + */ + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_TYPE_MASK UINT32_C(0x3f) + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_TYPE_SFT 0 + /* QP Async Notification */ + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_TYPE_QP_EVENT UINT32_C(0x38) + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_TYPE_LAST CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_TYPE_QP_EVENT + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Side buffer size in 16-byte units */ + uint32_t size; + uint8_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_V UINT32_C(0x1) + /* Event or command opcode. */ + uint8_t event; + /* Query extended RoCE statistics v2. */ + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_EVENT_QUERY_ROCE_STATS_EXT_V2 UINT32_C(0x98) + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_EVENT_LAST CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_EVENT_QUERY_ROCE_STATS_EXT_V2 + uint8_t reserved48[6]; +} creq_query_roce_stats_ext_v2_resp_t, *pcreq_query_roce_stats_ext_v2_resp_t; + +/* Query extended RoCE Stats command response side buffer structure. */ +/* creq_query_roce_stats_ext_v2_resp_sb (size:1920b/240B) */ + +typedef struct creq_query_roce_stats_ext_v2_resp_sb { + /* Command opcode. */ + uint8_t opcode; + /* Query extended RoCE statistics v2. */ + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_SB_OPCODE_QUERY_ROCE_STATS_EXT_V2 UINT32_C(0x98) + #define CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_SB_OPCODE_LAST CREQ_QUERY_ROCE_STATS_EXT_V2_RESP_SB_OPCODE_QUERY_ROCE_STATS_EXT_V2 + /* Status of the response. */ + uint8_t status; + /* Driver supplied handle to associate the command and the response. */ + uint16_t cookie; + /* Flags and attribs of the command. */ + uint16_t flags; + /* Size of the response buffer in 16-byte units. */ + uint8_t resp_size; + uint8_t rsvd; + /* Number of transmitted Atomic request packets without errors. */ + uint64_t tx_atomic_req_pkts; + /* Number of transmitted Read request packets without errors. */ + uint64_t tx_read_req_pkts; + /* Number of transmitted Read response packets without errors. */ + uint64_t tx_read_res_pkts; + /* Number of transmitted Write request packets without errors. */ + uint64_t tx_write_req_pkts; + /* Number of transmitted RC Send packets without errors. */ + uint64_t tx_rc_send_req_pkts; + /* + * Number of transmitted UD Send (including QP1) packets + * without errors. + */ + uint64_t tx_ud_send_req_pkts; + /* Number of transmitted CNPs. Includes DCN_CNPs. */ + uint64_t tx_cnp_pkts; + /* + * Number of transmitted RoCE packets. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t tx_roce_pkts; + /* + * Number of transmitted RoCE header and payload bytes. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t tx_roce_bytes; + /* + * Number of drops that occurred to lack of buffers. + * This count includes RC sends, RC writes with immediate, + * UD sends, RawEth, and QP1 packets dropped due to lack of buffers. + */ + uint64_t rx_out_of_buffer_pkts; + /* Number of packets that were received out of sequence. */ + uint64_t rx_out_of_sequence_pkts; + /* + * Number of duplicate read/atomic requests resulting in responder + * hardware retransmission. + */ + uint64_t dup_req; + /* + * Number of missing response packets resulting in hardware + * retransmission. + */ + uint64_t missing_resp; + /* + * Number of sequence error NAKs received resulting in hardware + * retransmission. + */ + uint64_t seq_err_naks_rcvd; + /* Number of RNR NAKs received resulting in hardware retransmission. */ + uint64_t rnr_naks_rcvd; + /* Number of timeouts resulting in hardware retransmission. */ + uint64_t to_retransmits; + /* Number of received Atomic request packets without errors. */ + uint64_t rx_atomic_req_pkts; + /* Number of received Read request packets without errors. */ + uint64_t rx_read_req_pkts; + /* Number of received Read response packets without errors. */ + uint64_t rx_read_res_pkts; + /* Number of received Write request packets without errors. */ + uint64_t rx_write_req_pkts; + /* Number of received RC Send packets without errors. */ + uint64_t rx_rc_send_pkts; + /* Number of received UD Send packets without errors. */ + uint64_t rx_ud_send_pkts; + /* Number of received DCN payload cut packets. */ + uint64_t rx_dcn_payload_cut; + /* Number of received ECN-marked packets. */ + uint64_t rx_ecn_marked_pkts; + /* Number of received CNP packets. Includes DCN_CNPs. */ + uint64_t rx_cnp_pkts; + /* + * Number of received RoCE packets including RoCE packets with errors. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t rx_roce_pkts; + /* + * Number of received RoCE header and payload bytes including RoCE + * packets with errors. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t rx_roce_bytes; + /* + * Number of received RoCE packets without errors. + * This includes RC, UD, RawEth, and QP1 packets + */ + uint64_t rx_roce_good_pkts; + /* + * Number of received RoCE header and payload bytes without errors. + * This includes RC, UD, RawEth, and QP1 packets. + */ + uint64_t rx_roce_good_bytes; +} creq_query_roce_stats_ext_v2_resp_sb_t, *pcreq_query_roce_stats_ext_v2_resp_sb_t; + /* RoCE function async event notifications. */ /* creq_func_event (size:128b/16B) */ @@ -69786,7 +78391,10 @@ typedef struct creq_func_event { #define CREQ_FUNC_EVENT_EVENT_TIM_ERROR UINT32_C(0xb) /* A VF sent a backchannel command request */ #define CREQ_FUNC_EVENT_EVENT_VF_COMM_REQUEST UINT32_C(0x80) - /* Communication resource (QPC, CQ, SRQ, MRW) exhausted, and resource array extension is enabled */ + /* + * Communication resource (QPC, CQ, SRQ, MRW) exhausted, and resource + * array extension is enabled. + */ #define CREQ_FUNC_EVENT_EVENT_RESOURCE_EXHAUSTED UINT32_C(0x81) #define CREQ_FUNC_EVENT_EVENT_LAST CREQ_FUNC_EVENT_EVENT_RESOURCE_EXHAUSTED uint8_t reserved48[6]; @@ -69894,7 +78502,10 @@ typedef struct creq_qp_event { #define CREQ_QP_EVENT_EVENT_QUERY_FUNC UINT32_C(0x83) /* Set function resources command response. */ #define CREQ_QP_EVENT_EVENT_SET_FUNC_RESOURCES UINT32_C(0x84) - /* Read the current state of any internal resource context. Can only be issued from a PF. */ + /* + * Read the current state of any internal resource context. Can only be + * issued from a PF. + */ #define CREQ_QP_EVENT_EVENT_READ_CONTEXT UINT32_C(0x85) /* Map TC to COS response. */ #define CREQ_QP_EVENT_EVENT_MAP_TC_TO_COS UINT32_C(0x8a) @@ -69909,8 +78520,8 @@ typedef struct creq_qp_event { /* Set LAG mode. */ #define CREQ_QP_EVENT_EVENT_SET_LINK_AGGR_MODE UINT32_C(0x8f) /* - * Query QP for a PF other than the requesting PF. Also can query for more - * than one QP. + * Query QP for a PF other than the requesting PF. Also can query for + * more than one QP. */ #define CREQ_QP_EVENT_EVENT_QUERY_QP_EXTEND UINT32_C(0x91) /* QP error notification event. */ @@ -69944,6 +78555,236 @@ typedef struct creq_qp_error_notification { uint8_t req_slow_path_state; /* requestor error reason */ uint8_t req_err_state_reason; + /* No error. */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_NO_ERROR UINT32_C(0x0) + /* + * Requester detected opcode error. + * * First, only, middle, last for incoming RDMA read + * responses are improperly ordered with respect to previous + * (PSN) packet. + * * First or middle packet is not full MTU size. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_OPCODE_ERROR UINT32_C(0x1) + /* + * Transport timeout retry limit exceeded. + * The requestor retried the same unacked PSN request packet + * too many times. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_TIMEOUT_RETRY_LIMIT UINT32_C(0x2) + /* + * RNR NAK retry limit exceeded. + * The requestor received an RNR NAK with the same NAK PSN + * too many times. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_RNR_TIMEOUT_RETRY_LIMIT UINT32_C(0x3) + /* + * NAK arrival, When NAK code is 1, Invalid Request. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_NAK_ARRIVAL_1 UINT32_C(0x4) + /* + * NAK arrival, When NAK code is 2, Remote Access Error. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_NAK_ARRIVAL_2 UINT32_C(0x5) + /* + * NAK arrival, When NAK code is 3, Remote Operational Error. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_NAK_ARRIVAL_3 UINT32_C(0x6) + /* + * NAK arrival. When NAK code is 4, Invalid RD Request. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_NAK_ARRIVAL_4 UINT32_C(0x7) + /* + * Local memory error. + * An SGE described an inaccessible memory. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_RX_MEMORY_ERROR UINT32_C(0x8) + /* + * Local memory error. + * An SGE described an inaccessible memory. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_TX_MEMORY_ERROR UINT32_C(0x9) + /* + * Read response length error. + * The read response payload size does not match the read + * length of the request. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_READ_RESP_LENGTH UINT32_C(0xa) + /* + * Invalid read response. + * A read response arrived and had a PSN that was not in the + * reply range of any outstanding read request on the ORRQ. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_INVALID_READ_RESP UINT32_C(0xb) + /* + * Illegal bind. + * * No MW with the specified R_Key exists. + * * No MR with the specified L_Key exists. + * * A bind request was performed on a window that was already + * bound. + * * A bind request was performed for an underlying MR that + * is not registered. + * * A bind request was performed for a memory area that exceeds + * the range of the underlying MR. + * * A bind request was performed with a set of permissions + * that are looser than the permissions of the underlying MR. + * * Domain error MW - When QP's PD does not match MW PD. + * * Domain error MR - When QP's PD does not match parent MR's + * PD. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_ILLEGAL_BIND UINT32_C(0xc) + /* + * Illegal fast register. + * * No MR with the specified L_Key exists. + * * A fast register request was performed on a non- + * physical MR. + * * A fast register request was performed on a physical MR + * that is already registered. + * * A fast register request was performed on a physical MR + * that does not have a page list allocated (has not been + * initialized). + * * The number of pages being registered exceeds the capacity + * of the physical MR. + * * The length of the registration is not possible with the + * actual number of pages provided. + * * Domain error - when QP's PD does not match PMR PD. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_ILLEGAL_FAST_REG UINT32_C(0xd) + /* + * Illegal invalidate. + * * No MR with the specified L_Key exists. + * * No MW with the specified R_Key exists. + * * An invalidate was performed against a non-physical MR. + * * An invalidate was performed against a physical MR that + * is not registered. + * * An invalidate was performed against a MW that is not + * bound. + * * The PD of the MR/MW being invalidated does not match the PD + * of the QP. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_ILLEGAL_INVALIDATE UINT32_C(0xe) + /* + * Completion Error. + * No CQE space available on queue, or CQ not in VALID state. + * This is a Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_CMP_ERROR UINT32_C(0xf) + /* + * Local memory error while retransmitting WQE. + * An SQ SGE described an inaccessible memory. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_RETRAN_LOCAL_ERROR UINT32_C(0x10) + /* + * Problem found in the format of a WQE in the SQ. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_WQE_FORMAT_ERROR UINT32_C(0x11) + /* + * Problem was found in the format of an ORRQ entry. + * This is a RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_ORRQ_FORMAT_ERROR UINT32_C(0x12) + /* + * A UD send attempted to use an invalid AVID. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_INVALID_AVID_ERROR UINT32_C(0x13) + /* + * A UD send attempted to use an AVID that is outside of its + * QP's protection domain. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_AV_DOMAIN_ERROR UINT32_C(0x14) + /* + * A load error occurred on an attempt to load the CQ Context. + * This is a Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_CQ_LOAD_ERROR UINT32_C(0x15) + /* + * There was an attempt to process a WQE from the SQ that + * corresponds to an operation that is unsupported for the + * corresponding QP. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_SERV_TYPE_ERROR UINT32_C(0x16) + /* + * There was an attempt to process a WQE from the SQ that + * corresponds to an operation that is unsupported for the + * corresponding QP, according to the supported_operations QPC + * field. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_INVALID_OP_ERROR UINT32_C(0x17) + /* + * A fatal error was detected on an attempt to read from + * or write to PCIe on the transmit side. This error is + * detected by the TX side (or CAGR), but has the priority + * of a Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_TX_PCI_ERROR UINT32_C(0x18) + /* + * A fatal error was detected on an attempt to read from + * or write to PCIe on the receive side. This error is detected + * by the RX side (or CAGR), but has the priority of a + * Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_RX_PCI_ERROR UINT32_C(0x19) + /* + * When processing a WQE from the SQ, TWE detected an error + * such that the wqe_size given in the header is larger than + * the delta between sq_work_idx and sq_prod_idx. This error + * has priority over the non-error case that occurs when TWE + * detects that it simply doesn't have enough slots fetched + * to execute the WQE during the current residency. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_PROD_WQE_MSMTCH_ERROR UINT32_C(0x1a) + /* + * When reading the MSN table to initiate HW retransmit, RWE + * found that to_retransmit_psn was not within the range defined + * by start_psn and next_psn in the corresponding MSN table + * entry. To_retransmit_psn must be greater than or equal to + * start_psn and less than next_psn in order for the range check + * to succeed. + * This is a RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_PSN_RANGE_CHECK_ERROR UINT32_C(0x1b) + /* + * While retransmitting, TWE detected one of several possible + * error detection scenarios related to the improper setup of + * retransmission. These include a category or errors known as + * retx_end_error where the retransmission end does not line up + * sequentially with the WQE index and PSN upon continuing on + * with the regular transmission that follows the + * retransmission. It also includes the error condition in which + * the retransmission Work Request has gen_dup_read_request set + * and the WQE fetched by TWE is not an RDMA Read or Atomic WQE. + * Please see TWE requirements for a full list of the various + * possible retransmit setup error cases. These error cases + * apply to H/W and F/W retransmission, alike. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_RETX_SETUP_ERROR UINT32_C(0x1c) + /* + * An express doorbell was posted that overflowed the SQ. The + * doorbell is dropped, along with all subsequent doorbells for + * this SQ. This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_SQ_OVERFLOW UINT32_C(0x1d) + #define CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_LAST CREQ_QP_ERROR_NOTIFICATION_REQ_ERR_STATE_REASON_REQ_SQ_OVERFLOW /* QP context id */ uint32_t xid; uint8_t v; @@ -69961,6 +78802,211 @@ typedef struct creq_qp_error_notification { /* responder slow path state */ uint8_t res_slow_path_state; uint8_t res_err_state_reason; + /* No error. */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_NO_ERROR UINT32_C(0x0) + /* + * Incoming Send, RDMA write, or RDMA read exceeds the maximum + * transfer length. Detected on RX first and only packets for + * write. Detected on RX request for read. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_EXCEED_MAX UINT32_C(0x1) + /* + * RDMA write payload size does not match write length. Detected + * when total write payload is not equal to the RDMA write + * length that was given in the first or only packet of the + * request. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_PAYLOAD_LENGTH_MISMATCH UINT32_C(0x2) + /* + * Send payload exceeds RQ/SRQ WQE buffer capacity. The total + * send payload that arrived is more than the size of the WQE + * buffer that was fetched from the RQ/SRQ. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_EXCEEDS_WQE UINT32_C(0x3) + /* + * Responder detected opcode error. + * * First, only, middle, last or incoming requests are + * improperly ordered with respect to previous (PSN) packet. + * * First or middle packet is not full MTU size. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_OPCODE_ERROR UINT32_C(0x4) + /* + * PSN sequence error retry limit exceeded. + * The responder encountered a PSN sequence error for the + * same PSN too many times. This can occur via implicit or + * explicit NAK. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_PSN_SEQ_ERROR_RETRY_LIMIT UINT32_C(0x5) + /* + * Invalid R_Key. + * An incoming request contained an R_Key that did not reference + * a valid MR/MW. This error may be detected by the RX engine + * for RDMA write or by the TX engine for RDMA read + * (detected while servicing IRRQ). + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RX_INVALID_R_KEY UINT32_C(0x6) + /* + * Domain error. + * An incoming request specified an R_Key which + * referenced a MR/MW that was not in the same PD as the QP on + * which the request arrived. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RX_DOMAIN_ERROR UINT32_C(0x7) + /* + * No permission. + * An incoming request contained an R_Key that referenced a + * MR/MW which did not have the access permission needed for + * the operation. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RX_NO_PERMISSION UINT32_C(0x8) + /* + * Range error. + * An incoming request had a combination of R_Key,VA, and + * length that was out of bounds of the associated MR/MW. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RX_RANGE_ERROR UINT32_C(0x9) + /* + * Invalid R_Key. + * An incoming request contained an R_Key that did not + * reference a valid MR/MW. This error may be detected + * by the RX engine for RDMA write or by the TX engine + * for RDMA read (detected while servicing IRRQ). + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_TX_INVALID_R_KEY UINT32_C(0xa) + /* + * Domain error. + * An incoming request specified an R_Key which referenced + * a MR/MW that was not in the same PD as the QP on + * which the request arrived. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_TX_DOMAIN_ERROR UINT32_C(0xb) + /* + * No permission. + * An incoming request contained an R_Key that referenced a + * MR/MW which did not have the access permission needed for + * the operation. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_TX_NO_PERMISSION UINT32_C(0xc) + /* + * Range error. + * An incoming request had a combination of R_Key, VA, and + * length that was out of bounds of the associated MR/MW. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_TX_RANGE_ERROR UINT32_C(0xd) + /* + * IRRQ overflow. + * The peer sent us more RDMA read or atomic requests than + * the negotiated maximum. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_IRRQ_OFLOW UINT32_C(0xe) + /* + * Unsupported opcode. + * The peer sent us a request with an opcode for a request + * type that is not supported on this QP. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_UNSUPPORTED_OPCODE UINT32_C(0xf) + /* + * Unaligned atomic operation. The VA of an atomic request + * is on a memory boundary that prevents atomic execution. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_UNALIGN_ATOMIC UINT32_C(0x10) + /* + * Remote invalidate error. + * A send with invalidate request arrived in which the + * R_Key to invalidate did not describe a MR/MW which could + * be invalidated. RQ WQE completes with error status. + * This error is only reported if the send operation did + * not fail. If the send operation failed then the remote + * invalidate error is not reported. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_REM_INVALIDATE UINT32_C(0x11) + /* + * Local memory error. An RQ/SRQ SGE described an inaccessible + * memory. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_MEMORY_ERROR UINT32_C(0x12) + /* + * SRQ in error. The QP is moving to error state because it + * found SRQ it uses in error. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_SRQ_ERROR UINT32_C(0x13) + /* + * Completion error. No CQE space available on queue or CQ not + * in VALID state. + * This is a Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_CMP_ERROR UINT32_C(0x14) + /* + * Invalid R_Key while resending responses to duplicate request. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_INVALID_DUP_RKEY UINT32_C(0x15) + /* + * Problem was found in the format of a WQE in the RQ/SRQ. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_WQE_FORMAT_ERROR UINT32_C(0x16) + /* + * Problem was found in the format of an IRRQ entry. + * This is a TX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_IRRQ_FORMAT_ERROR UINT32_C(0x17) + /* + * A load error occurred on an attempt to load the CQ Context. + * This is a Completion Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_CQ_LOAD_ERROR UINT32_C(0x18) + /* + * A load error occurred on an attempt to load the SRQ Context. + * This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_SRQ_LOAD_ERROR UINT32_C(0x19) + /* + * A fatal error was detected on an attempt to read from or + * write to PCIe on the transmit side. This error is detected + * by the TX side, but has the priority of a Completion + * Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_TX_PCI_ERROR UINT32_C(0x1b) + /* + * A fatal error was detected on an attempt to read from or + * write to PCIe on the receive side. This error is detected + * by the RX side (or CAGR), but has the priority of a Completion + * Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RX_PCI_ERROR UINT32_C(0x1c) + /* + * When searching the IRRQ to respond to a duplicate request, + * RWE could not find the duplicate request in the entire IRRQ. + * This is a RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_PSN_NOT_FOUND UINT32_C(0x1d) + /* + * An express doorbell was posted that overflowed the RQ. The + * doorbell is dropped, along with all subsequent doorbells for + * this RQ. This is an RX Detected Error. + */ + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RQ_OVERFLOW UINT32_C(0x1e) + #define CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_LAST CREQ_QP_ERROR_NOTIFICATION_RES_ERR_STATE_REASON_RES_RQ_OVERFLOW /* * Final SQ Consumer Index value. Any additional SQ WQEs will * have to be completed by the user provider. @@ -70031,78 +79077,165 @@ typedef struct sq_base { /* This field defines the type of SQ WQE. */ uint8_t wqe_type; /* Send */ - #define SQ_BASE_WQE_TYPE_SEND UINT32_C(0x0) + #define SQ_BASE_WQE_TYPE_SEND UINT32_C(0x0) /* * Send with Immediate * * Allowed only on reliable connection (RC) and * unreliable datagram (UD) SQs. */ - #define SQ_BASE_WQE_TYPE_SEND_W_IMMEAD UINT32_C(0x1) + #define SQ_BASE_WQE_TYPE_SEND_W_IMMEAD UINT32_C(0x1) /* * Send with Invalidate. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_SEND_W_INVALID UINT32_C(0x2) + #define SQ_BASE_WQE_TYPE_SEND_W_INVALID UINT32_C(0x2) /* * RDMA Write. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_WRITE_WQE UINT32_C(0x4) + #define SQ_BASE_WQE_TYPE_WRITE_WQE UINT32_C(0x4) /* * RDMA Write with Immediate. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_WRITE_W_IMMEAD UINT32_C(0x5) + #define SQ_BASE_WQE_TYPE_WRITE_W_IMMEAD UINT32_C(0x5) /* * RDMA Read. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_READ_WQE UINT32_C(0x6) + #define SQ_BASE_WQE_TYPE_READ_WQE UINT32_C(0x6) /* * Atomic Compare/Swap. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_ATOMIC_CS UINT32_C(0x8) + #define SQ_BASE_WQE_TYPE_ATOMIC_CS UINT32_C(0x8) /* * Atomic Fetch/Add. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_ATOMIC_FA UINT32_C(0xb) + #define SQ_BASE_WQE_TYPE_ATOMIC_FA UINT32_C(0xb) /* * Local Invalidate. * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_LOCAL_INVALID UINT32_C(0xc) + #define SQ_BASE_WQE_TYPE_LOCAL_INVALID UINT32_C(0xc) /* * FR-PMR (Fast Register Physical Memory Region) * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_FR_PMR UINT32_C(0xd) + #define SQ_BASE_WQE_TYPE_FR_PMR UINT32_C(0xd) /* * Memory Bind * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_BIND UINT32_C(0xe) + #define SQ_BASE_WQE_TYPE_BIND UINT32_C(0xe) /* * FR-PPMR (Fast Register Proxy Physical Memory Region) * * Allowed only on reliable connection (RC) SQs. */ - #define SQ_BASE_WQE_TYPE_FR_PPMR UINT32_C(0xf) - #define SQ_BASE_WQE_TYPE_LAST SQ_BASE_WQE_TYPE_FR_PPMR + #define SQ_BASE_WQE_TYPE_FR_PPMR UINT32_C(0xf) + /* Send V3 */ + #define SQ_BASE_WQE_TYPE_SEND_V3 UINT32_C(0x10) + /* + * Send with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_SEND_W_IMMED_V3 UINT32_C(0x11) + /* + * Send with Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_SEND_W_INVALID_V3 UINT32_C(0x12) + /* + * UD Send V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_BASE_WQE_TYPE_UDSEND_V3 UINT32_C(0x13) + /* + * UD Send with Immediate V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_BASE_WQE_TYPE_UDSEND_W_IMMED_V3 UINT32_C(0x14) + /* + * RDMA Write V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_WRITE_WQE_V3 UINT32_C(0x15) + /* + * RDMA Write with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_WRITE_W_IMMED_V3 UINT32_C(0x16) + /* + * RDMA Read V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_READ_WQE_V3 UINT32_C(0x17) + /* + * Atomic Compare/Swap V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_ATOMIC_CS_V3 UINT32_C(0x18) + /* + * Atomic Fetch/Add V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_ATOMIC_FA_V3 UINT32_C(0x19) + /* + * Local Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_LOCAL_INVALID_V3 UINT32_C(0x1a) + /* + * FR-PMR (Fast Register Physical Memory Region) V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_FR_PMR_V3 UINT32_C(0x1b) + /* + * Memory Bind V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BASE_WQE_TYPE_BIND_V3 UINT32_C(0x1c) + /* RawEth/QP1 Send V3 */ + #define SQ_BASE_WQE_TYPE_RAWQP1SEND_V3 UINT32_C(0x1d) + /* Change UDP Source Port V3 */ + #define SQ_BASE_WQE_TYPE_CHANGE_UDPSRCPORT_V3 UINT32_C(0x1e) + #define SQ_BASE_WQE_TYPE_LAST SQ_BASE_WQE_TYPE_CHANGE_UDPSRCPORT_V3 uint8_t unused_0[7]; } sq_base_t, *psq_base_t; +/* + * Most SQ WQEs contain SGEs used to define the SGL used to map payload + * data in host memory. The number of SGE structures is defined by the + * wqe_size field. SGE structures are aligned to 16B boundaries. + * + * In backward-compatible modes there can be 2, 4 or 6 SGEs (based on + * the mode). In variable-sized WQE mode there can be 0-30 SGE + * structures. + */ /* sq_sge (size:128b/16B) */ typedef struct sq_sge { @@ -70276,7 +79409,7 @@ typedef struct sq_send { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -70292,7 +79425,7 @@ typedef struct sq_send { uint32_t length; /* * When in the SQ of a UD QP, indicates the q_key to be used in - * the transmitted packet. However, if the most significant bit + * the transmitted packet. However, if the most significant bit * of this field is set, then the q_key will be taken from QP * context, rather than from this field. * @@ -70331,7 +79464,7 @@ typedef struct sq_send { * SGEs based on the wqe_size field. * * When inline=1, this area is filled with payload data for the - * send based on the length_or_AVID field. Bits [7:0] of word 0 + * send based on the length_or_AVID field. Bits [7:0] of word 0 * hold the first byte to go out on the wire. */ uint32_t data[24]; @@ -70412,7 +79545,7 @@ typedef struct sq_send_hdr { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -70428,7 +79561,7 @@ typedef struct sq_send_hdr { uint32_t length; /* * When in the SQ of a UD QP, indicates the q_key to be used in - * the transmitted packet. However, if the most significant bit + * the transmitted packet. However, if the most significant bit * of this field is set, then the q_key will be taken from QP * context, rather than from this field. * @@ -70511,7 +79644,7 @@ typedef struct sq_send_raweth_qp1 { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -70532,7 +79665,7 @@ typedef struct sq_send_raweth_qp1 { */ #define SQ_SEND_RAWETH_QP1_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) /* - * If set to 1, the controller replaces the IP checksum of the + * If set to 1, the controller replaces the IP checksum of the * normal packets, or the inner IP checksum of the encapsulated * packets with the hardware calculated IP checksum for the * packet associated with this descriptor. @@ -70546,9 +79679,9 @@ typedef struct sq_send_raweth_qp1 { * * This bit must be valid on the first BD of a packet. * - * Packet must be 64B or longer when this flag is set. It is not - * usefull to use this bit with any form of TX offload such as - * CSO or LSO. The intent is that the packet from the host already + * Packet must be 64B or longer when this flag is set. It is not + * useful to use this bit with any form of TX offload such as + * CSO or LSO. The intent is that the packet from the host already * has a valid Ethernet CRC on the packet. */ #define SQ_SEND_RAWETH_QP1_LFLAGS_NOCRC UINT32_C(0x4) @@ -70562,7 +79695,7 @@ typedef struct sq_send_raweth_qp1 { /* * If set to 1, The controller replaces the tunnel IP checksum * field with hardware calculated IP checksum for the IP header - * of the packet associated with this descriptor. In case of + * of the packet associated with this descriptor. In case of * VXLAN, the controller also replaces the outer header UDP * checksum with hardware calculated UDP checksum for the packet * associated with this descriptor. @@ -70570,12 +79703,12 @@ typedef struct sq_send_raweth_qp1 { #define SQ_SEND_RAWETH_QP1_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) /* * If set to '1', then the RoCE ICRC will be appended to the - * packet. Packet must be a valid RoCE format packet. + * packet. Packet must be a valid RoCE format packet. */ #define SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC UINT32_C(0x100) /* * If set to '1', then the FCoE CRC will be appended to the - * packet. Packet must be a valid FCoE format packet. + * packet. Packet must be a valid FCoE format packet. */ #define SQ_SEND_RAWETH_QP1_LFLAGS_FCOE_CRC UINT32_C(0x200) /* @@ -70655,7 +79788,7 @@ typedef struct sq_send_raweth_qp1 { * SGEs based on the wqe_size field. * * When inline=1, this area is filled with payload data for the - * send based on the length_or_AVID field. Bits [7:0] of word 0 + * send based on the length_or_AVID field. Bits [7:0] of word 0 * hold the first byte to go out on the wire. */ uint32_t data[24]; @@ -70708,7 +79841,7 @@ typedef struct sq_send_raweth_qp1_hdr { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -70729,7 +79862,7 @@ typedef struct sq_send_raweth_qp1_hdr { */ #define SQ_SEND_RAWETH_QP1_HDR_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) /* - * If set to 1, the controller replaces the IP checksum of the + * If set to 1, the controller replaces the IP checksum of the * normal packets, or the inner IP checksum of the encapsulated * packets with the hardware calculated IP checksum for the * packet associated with this descriptor. @@ -70743,9 +79876,9 @@ typedef struct sq_send_raweth_qp1_hdr { * * This bit must be valid on the first BD of a packet. * - * Packet must be 64B or longer when this flag is set. It is not - * usefull to use this bit with any form of TX offload such as - * CSO or LSO. The intent is that the packet from the host already + * Packet must be 64B or longer when this flag is set. It is not + * useful to use this bit with any form of TX offload such as + * CSO or LSO. The intent is that the packet from the host already * has a valid Ethernet CRC on the packet. */ #define SQ_SEND_RAWETH_QP1_HDR_LFLAGS_NOCRC UINT32_C(0x4) @@ -70759,7 +79892,7 @@ typedef struct sq_send_raweth_qp1_hdr { /* * If set to 1, The controller replaces the tunnel IP checksum * field with hardware calculated IP checksum for the IP header - * of the packet associated with this descriptor. In case of + * of the packet associated with this descriptor. In case of * VXLAN, the controller also replaces the outer header UDP * checksum with hardware calculated UDP checksum for the packet * associated with this descriptor. @@ -70767,12 +79900,12 @@ typedef struct sq_send_raweth_qp1_hdr { #define SQ_SEND_RAWETH_QP1_HDR_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) /* * If set to '1', then the RoCE ICRC will be appended to the - * packet. Packet must be a valid RoCE format packet. + * packet. Packet must be a valid RoCE format packet. */ #define SQ_SEND_RAWETH_QP1_HDR_LFLAGS_ROCE_CRC UINT32_C(0x100) /* * If set to '1', then the FCoE CRC will be appended to the - * packet. Packet must be a valid FCoE format packet. + * packet. Packet must be a valid FCoE format packet. */ #define SQ_SEND_RAWETH_QP1_HDR_LFLAGS_FCOE_CRC UINT32_C(0x200) /* @@ -70904,7 +80037,7 @@ typedef struct sq_rdma { #define SQ_RDMA_FLAGS_SE UINT32_C(0x8) /* * Indicate that inline data is posted to the SQ following - * this WQE. This bit may be 1 only for write operations. + * this WQE. This bit may be 1 only for write operations. */ #define SQ_RDMA_FLAGS_INLINE UINT32_C(0x10) /* @@ -70923,7 +80056,7 @@ typedef struct sq_rdma { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -70957,7 +80090,7 @@ typedef struct sq_rdma { * SGEs based on the wqe_size field. * * When inline=1, this area is filled with payload data for the - * write based on the length field. Bits [7:0] of word 0 + * write based on the length field. Bits [7:0] of word 0 * hold the first byte to go out on the wire. */ uint32_t data[24]; @@ -71018,7 +80151,7 @@ typedef struct sq_rdma_hdr { #define SQ_RDMA_HDR_FLAGS_SE UINT32_C(0x8) /* * Indicate that inline data is posted to the SQ following - * this WQE. This bit may be 1 only for write operations. + * this WQE. This bit may be 1 only for write operations. */ #define SQ_RDMA_HDR_FLAGS_INLINE UINT32_C(0x10) /* @@ -71037,7 +80170,7 @@ typedef struct sq_rdma_hdr { * valid 16 bytes units other than the WQE structure can be * SGEs (Scatter Gather Elements) OR inline data. * - * While this field defines the valid WQE size. The actual + * While this field defines the valid WQE size. The actual * total WQE size is always 128B. */ uint8_t wqe_size; @@ -71146,7 +80279,7 @@ typedef struct sq_atomic { /* * The first 16B of the data field must be filled with a single * SGE. This will be used to store the return value from the - * Atomic Ack response. The size of the single SGE must be 8B. + * Atomic Ack response. The size of the single SGE must be 8B. */ uint32_t data[24]; } sq_atomic_t, *psq_atomic_t; @@ -71405,8 +80538,8 @@ typedef struct sq_fr_pmr { */ #define SQ_FR_PMR_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -71575,20 +80708,21 @@ typedef struct sq_fr_pmr { #define SQ_FR_PMR_NUMLEVELS_SFT 6 /* * A zero level PBL means that the VA is the physical address used - * for the operation. No translation is done by the PTU. + * for the operation. No translation is done by the PTU. */ #define SQ_FR_PMR_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 6) /* * A one layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PBE values that point to actual pg_size physical pages. + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical pages. */ #define SQ_FR_PMR_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 6) /* * A two layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PDE values that in turn point to pbl_pg_size physical pages that contain - * PBE values that point to actual physical pages. + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size physical + * pages that contain PBE values that point to actual physical + * pages. */ #define SQ_FR_PMR_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 6) #define SQ_FR_PMR_NUMLEVELS_LAST SQ_FR_PMR_NUMLEVELS_LAYER2 @@ -71647,8 +80781,8 @@ typedef struct sq_fr_pmr_hdr { */ #define SQ_FR_PMR_HDR_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -71817,20 +80951,21 @@ typedef struct sq_fr_pmr_hdr { #define SQ_FR_PMR_HDR_NUMLEVELS_SFT 6 /* * A zero level PBL means that the VA is the physical address used - * for the operation. No translation is done by the PTU. + * for the operation. No translation is done by the PTU. */ #define SQ_FR_PMR_HDR_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 6) /* * A one layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PBE values that point to actual pg_size physical pages. + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical pages. */ #define SQ_FR_PMR_HDR_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 6) /* * A two layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PDE values that in turn point to pbl_pg_size physical pages that contain - * PBE values that point to actual physical pages. + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size physical + * pages that contain PBE values that point to actual physical + * pages. */ #define SQ_FR_PMR_HDR_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 6) #define SQ_FR_PMR_HDR_NUMLEVELS_LAST SQ_FR_PMR_HDR_NUMLEVELS_LAYER2 @@ -71887,8 +81022,8 @@ typedef struct sq_fr_ppmr { */ #define SQ_FR_PPMR_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -72061,20 +81196,21 @@ typedef struct sq_fr_ppmr { #define SQ_FR_PPMR_NUMLEVELS_SFT 6 /* * A zero level PBL means that the VA is the physical address used - * for the operation. No translation is done by the PTU. + * for the operation. No translation is done by the PTU. */ #define SQ_FR_PPMR_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 6) /* * A one layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PBE values that point to actual pg_size physical pages. + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical pages. */ #define SQ_FR_PPMR_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 6) /* * A two layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PDE values that in turn point to pbl_pg_size physical pages that contain - * PBE values that point to actual physical pages. + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size physical + * pages that contain PBE values that point to actual physical + * pages. */ #define SQ_FR_PPMR_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 6) #define SQ_FR_PPMR_NUMLEVELS_LAST SQ_FR_PPMR_NUMLEVELS_LAYER2 @@ -72133,8 +81269,8 @@ typedef struct sq_fr_ppmr_hdr { */ #define SQ_FR_PPMR_HDR_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -72307,20 +81443,21 @@ typedef struct sq_fr_ppmr_hdr { #define SQ_FR_PPMR_HDR_NUMLEVELS_SFT 6 /* * A zero level PBL means that the VA is the physical address used - * for the operation. No translation is done by the PTU. + * for the operation. No translation is done by the PTU. */ #define SQ_FR_PPMR_HDR_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 6) /* * A one layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PBE values that point to actual pg_size physical pages. + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical pages. */ #define SQ_FR_PPMR_HDR_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 6) /* * A two layer translation is provided between the logical and - * physical address. The PBL points to a physical page that contains - * PDE values that in turn point to pbl_pg_size physical pages that contain - * PBE values that point to actual physical pages. + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size physical + * pages that contain PBE values that point to actual physical + * pages. */ #define SQ_FR_PPMR_HDR_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 6) #define SQ_FR_PPMR_HDR_NUMLEVELS_LAST SQ_FR_PPMR_HDR_NUMLEVELS_LAYER2 @@ -72383,8 +81520,8 @@ typedef struct sq_bind { */ #define SQ_BIND_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -72394,7 +81531,7 @@ typedef struct sq_bind { * Local Write Access. * * Local accesses are never allowed for memory windows, so this - * bit must always be zero in a bind WQE. If this bit is ever + * bit must always be zero in a bind WQE. If this bit is ever * set, the bind will fail with an errored completion. */ #define SQ_BIND_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) @@ -72404,23 +81541,25 @@ typedef struct sq_bind { * Remote Write Access. * * Note that, if this bit is set, then the parent region to which - * the window is being bound must allow local writes. If this is not - * the case, then the bind will fail with an errored completion. + * the window is being bound must allow local writes. If this is + * not the case, then the bind will fail with an errored + * completion. */ #define SQ_BIND_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) /* * Remote Atomic Access. * * Note that, if this bit is set, then the parent region to which - * the window is being bound must allow local writes. If this is not - * the case, then the bind will fail with an errored completion. + * the window is being bound must allow local writes. If this is + * not the case, then the bind will fail with an errored + * completion. */ #define SQ_BIND_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) /* * Window Binding Allowed. * * It is never allowed to bind windows to windows, so this bit - * must always be zero in a bind WQE. If this bit is ever set, + * must always be zero in a bind WQE. If this bit is ever set, * the bind will fail with an errored completion. */ #define SQ_BIND_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) @@ -72429,27 +81568,28 @@ typedef struct sq_bind { uint8_t mw_type_zero_based; /* * If this bit is set, then the newly-bound memory window will be - * zero-based. If clear, then the newly-bound memory window will be + * zero-based. If clear, then the newly-bound memory window will be * non-zero-based. */ #define SQ_BIND_ZERO_BASED UINT32_C(0x1) /* - * If type1 is specified, then this WQE performs a "bind memory window" - * operation on a type1 window. If type2 is specified, then this WQE - * performs a "post send bind memory window" operation on a type2 - * window. + * If type1 is specified, then this WQE performs a "bind memory + * window" operation on a type1 window. If type2 is specified, then + * this WQE performs a "post send bind memory window" operation on a + * type2 window. * - * Note that the bind WQE cannot change the type of the memory window. + * Note that the bind WQE cannot change the type of the memory + * window. * - * If a "bind memory window" operation is attempted on a memory window - * that was allocated as type2, then the bind will fail with an errored - * completion, as "bind memory window" is allowed only on type1 memory - * windows. + * If a "bind memory window" operation is attempted on a memory + * window that was allocated as type2, then the bind will fail with + * an errored completion, as "bind memory window" is allowed only on + * type1 memory windows. * - * Similarly, if a "post send bind memory window" operation is attempted - * on a memory window that was allocated as type1, then the bind will fail - * with an errored completions, as "post send bind memory window" is allowed - * only on type2 memory windows. + * Similarly, if a "post send bind memory window" operation is + * attempted on a memory window that was allocated as type1, then the + * bind will fail with an errored completions, as "post send bind + * memory window" is allowed only on type2 memory windows. */ #define SQ_BIND_MW_TYPE UINT32_C(0x2) /* Type 1 Bind Memory Window */ @@ -72536,8 +81676,8 @@ typedef struct sq_bind_hdr { */ #define SQ_BIND_HDR_FLAGS_DEBUG_TRACE UINT32_C(0x40) /* - * This is the new access control for the MR. '1' means - * the operation is allowed. '0' means operation is + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is * not allowed. */ uint8_t access_cntl; @@ -72547,7 +81687,7 @@ typedef struct sq_bind_hdr { * Local Write Access. * * Local accesses are never allowed for memory windows, so this - * bit must always be zero in a bind WQE. If this bit is ever + * bit must always be zero in a bind WQE. If this bit is ever * set, the bind will fail with an errored completion. */ #define SQ_BIND_HDR_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) @@ -72557,23 +81697,25 @@ typedef struct sq_bind_hdr { * Remote Write Access. * * Note that, if this bit is set, then the parent region to which - * the window is being bound must allow local writes. If this is not - * the case, then the bind will fail with an errored completion. + * the window is being bound must allow local writes. If this is + * not the case, then the bind will fail with an errored + * completion. */ #define SQ_BIND_HDR_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) /* * Remote Atomic Access. * * Note that, if this bit is set, then the parent region to which - * the window is being bound must allow local writes. If this is not - * the case, then the bind will fail with an errored completion. + * the window is being bound must allow local writes. If this is + * not the case, then the bind will fail with an errored + * completion. */ #define SQ_BIND_HDR_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) /* * Window Binding Allowed. * * It is never allowed to bind windows to windows, so this bit - * must always be zero in a bind WQE. If this bit is ever set, + * must always be zero in a bind WQE. If this bit is ever set, * the bind will fail with an errored completion. */ #define SQ_BIND_HDR_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) @@ -72582,27 +81724,28 @@ typedef struct sq_bind_hdr { uint8_t mw_type_zero_based; /* * If this bit is set, then the newly-bound memory window will be - * zero-based. If clear, then the newly-bound memory window will be + * zero-based. If clear, then the newly-bound memory window will be * non-zero-based. */ #define SQ_BIND_HDR_ZERO_BASED UINT32_C(0x1) /* - * If type1 is specified, then this WQE performs a "bind memory window" - * operation on a type1 window. If type2 is specified, then this WQE - * performs a "post send bind memory window" operation on a type2 - * window. + * If type1 is specified, then this WQE performs a "bind memory + * window" operation on a type1 window. If type2 is specified, then + * this WQE performs a "post send bind memory window" operation on a + * type2 window. * - * Note that the bind WQE cannot change the type of the memory window. + * Note that the bind WQE cannot change the type of the memory + * window. * - * If a "bind memory window" operation is attempted on a memory window - * that was allocated as type2, then the bind will fail with an errored - * completion, as "bind memory window" is allowed only on type1 memory - * windows. + * If a "bind memory window" operation is attempted on a memory + * window that was allocated as type2, then the bind will fail with + * an errored completion, as "bind memory window" is allowed only on + * type1 memory windows. * - * Similarly, if a "post send bind memory window" operation is attempted - * on a memory window that was allocated as type1, then the bind will fail - * with an errored completions, as "post send bind memory window" is allowed - * only on type2 memory windows. + * Similarly, if a "post send bind memory window" operation is + * attempted on a memory window that was allocated as type1, then the + * bind will fail with an errored completions, as "post send bind + * memory window" is allowed only on type2 memory windows. */ #define SQ_BIND_HDR_MW_TYPE UINT32_C(0x2) /* Type 1 Bind Memory Window */ @@ -72634,6 +81777,2736 @@ typedef struct sq_bind_hdr { uint8_t reserved24[3]; } sq_bind_hdr_t, *psq_bind_hdr_t; +/* + * This V3 version of structure is not accessible from host software, but is documented here (in the SW section) anyway. + * This is the MSN Table (located in IQM). The table is written by the RoCE transmitter when sending wire operation WQEs. It is used to provide the RoCE receiver with information about the SQ WQEs in order to make requester completions and to perform requester HW retransmission. The number of entries in the table is configured in the QPC and must be equal to the maximum number of WQEs that can be present in the SQ at one time, rounded up to the nearest power of two. + */ +/* sq_msn_search_v3 (size:128b/16B) */ + +typedef struct sq_msn_search_v3 { + uint64_t idx_psn; + /* Start PSN of the WQE. */ + #define SQ_MSN_SEARCH_V3_START_PSN_MASK UINT32_C(0xffffff) + #define SQ_MSN_SEARCH_V3_START_PSN_SFT 0 + /* Next PSN. Equal to the start PSN of the next WQE. */ + #define SQ_MSN_SEARCH_V3_NEXT_PSN_MASK UINT32_C(0xffffff000000)L + #define SQ_MSN_SEARCH_V3_NEXT_PSN_SFT 24 + /* + * Start index. For variable-size WQEs, this field indicates the + * starting slot index that corresponds to the WQE. In + * backward-compatible mode, this is the starting WQE index. + */ + #define SQ_MSN_SEARCH_V3_START_IDX_MASK UINT32_C(0xffff000000000000)L + #define SQ_MSN_SEARCH_V3_START_IDX_SFT 48 + /* + * This value will be returned in the completion if the completion + * is signaled. + */ + uint32_t wqe_opaque; + /* The size of the WQE in units of 16B chunks. */ + uint8_t wqe_size; + uint8_t signal; + /* Set if completion signaling is requested. */ + #define SQ_MSN_SEARCH_V3_SGNLD UINT32_C(0x1) + /* + * Set if at least one signaled local memory operation WQE is + * present in the SQ between the previous wire-operation WQE + * and this WQE. + */ + #define SQ_MSN_SEARCH_V3_PREV_SGNLD_LOCAL_MEM_WQE UINT32_C(0x2) + uint16_t reserved; +} sq_msn_search_v3_t, *psq_msn_search_v3_t; + +/* SQ Send WQE V3 for RC SQs. */ +/* sq_send_v3 (size:1024b/128B) */ + +typedef struct sq_send_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* Send V3 */ + #define SQ_SEND_V3_WQE_TYPE_SEND_V3 UINT32_C(0x10) + /* + * Send with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_SEND_V3_WQE_TYPE_SEND_W_IMMED_V3 UINT32_C(0x11) + /* + * Send with Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_SEND_V3_WQE_TYPE_SEND_W_INVALID_V3 UINT32_C(0x12) + #define SQ_SEND_V3_WQE_TYPE_LAST SQ_SEND_V3_WQE_TYPE_SEND_W_INVALID_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_SEND_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_SEND_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_SEND_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + */ + #define SQ_SEND_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_SEND_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_SEND_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_SEND_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * Note: Since the WQE header consumes only one slot (16 bytes) + * for this type of WQE, and the maximum number of SGEs supported + * by the device is 30, this field must never exceed 31. + */ + #define SQ_SEND_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_SEND_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_SEND_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_SEND_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Either invalidate key (R_Key of the remote host) that will + * be send with IETH (Invalidate ETH) if wqe_type is of Send + * with Invalidate, or immediate value that will be sent with + * ImmDt header if wqe_type is Send with Immediate. + */ + uint32_t inv_key_or_imm_data; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_SEND_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_SEND_V3_TIMESTAMP_SFT 0 + /* + * When inline=0, then this area is filled with from 1 to 30 SGEs + * based on the wqe_size field. + * + * When inline=1, this area is filled with payload data for the + * send. Length of data is described in the inline_length field. + * Bits [7:0] of word 0 hold the first byte to go out on the wire. + */ + uint32_t data[28]; +} sq_send_v3_t, *psq_send_v3_t; + +/* Send SQ WQE V3 header. */ +/* sq_send_hdr_v3 (size:128b/16B) */ + +typedef struct sq_send_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* Send V3 */ + #define SQ_SEND_HDR_V3_WQE_TYPE_SEND_V3 UINT32_C(0x10) + /* + * Send with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_SEND_HDR_V3_WQE_TYPE_SEND_W_IMMED_V3 UINT32_C(0x11) + /* + * Send with Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_SEND_HDR_V3_WQE_TYPE_SEND_W_INVALID_V3 UINT32_C(0x12) + #define SQ_SEND_HDR_V3_WQE_TYPE_LAST SQ_SEND_HDR_V3_WQE_TYPE_SEND_W_INVALID_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_SEND_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_SEND_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_SEND_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + */ + #define SQ_SEND_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_SEND_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_SEND_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_SEND_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * Note: Since the WQE header consumes only one slot (16 bytes) + * for this type of WQE, and the maximum number of SGEs supported + * by the device is 30, this field must never exceed 31. + */ + #define SQ_SEND_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_SEND_HDR_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_SEND_HDR_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_SEND_HDR_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Either invalidate key (R_Key of the remote host) that will + * be send with IETH (Invalidate ETH) if wqe_type is of Send + * with Invalidate, or immediate value that will be sent with + * ImmDt header if wqe_type is Send with Immediate. + */ + uint32_t inv_key_or_imm_data; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_SEND_HDR_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_SEND_HDR_V3_TIMESTAMP_SFT 0 +} sq_send_hdr_v3_t, *psq_send_hdr_v3_t; + +/* SQ WQE V3 for Raw Ethernet and QP1 */ +/* sq_rawqp1send_v3 (size:1024b/128B) */ + +typedef struct sq_rawqp1send_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* RawEth/QP1 Send V3 */ + #define SQ_RAWQP1SEND_V3_WQE_TYPE_RAWQP1SEND_V3 UINT32_C(0x1d) + #define SQ_RAWQP1SEND_V3_WQE_TYPE_LAST SQ_RAWQP1SEND_V3_WQE_TYPE_RAWQP1SEND_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_RAWQP1SEND_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_RAWQP1SEND_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_RAWQP1SEND_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_RAWQP1SEND_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_RAWQP1SEND_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_RAWQP1SEND_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * All bits in this field must be valid on the first BD of a packet. + * Their value on other BDs of the packet will be ignored. + */ + uint16_t lflags; + /* + * If set to 1, the controller replaces the TCP/UPD checksum + * fields of normal TCP/UPD checksum, or the inner TCP/UDP + * checksum field of the encapsulated TCP/UDP packets with the + * hardware calculated TCP/UDP checksum for the packet associated + * with this descriptor. + * + * This bit must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) + /* + * If set to 1, the controller replaces the IP checksum of the + * normal packets, or the inner IP checksum of the encapsulated + * packets with the hardware calculated IP checksum for the + * packet associated with this descriptor. + * + * This bit must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_IP_CHKSUM UINT32_C(0x2) + /* + * If set to 1, the controller will not append an Ethernet CRC + * to the end of the frame. + * + * This bit must be valid on the first BD of a packet. + * + * Packet must be 64B or longer when this flag is set. It is not + * useful to use this bit with any form of TX offload such as + * CSO or LSO. The intent is that the packet from the host already + * has a valid Ethernet CRC on the packet. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_NOCRC UINT32_C(0x4) + /* + * If set to 1, The controller replaces the tunnel IP checksum + * field with hardware calculated IP checksum for the IP header + * of the packet associated with this descriptor. In case of + * VXLAN, the controller also replaces the outer header UDP + * checksum with hardware calculated UDP checksum for the packet + * associated with this descriptor. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) + /* + * If set to 1, The controller replaces the Outer-tunnel IP + * checksum field with hardware calculated IP checksum for the IP + * header of the packet associated with this descriptor. + * + * For outer UDP checksum, it will be the following behavior for + * all cases independent of settings of inner LSO and checksum + * offload BD flags: + * + * - If outer UDP checksum is 0, then do not update it. + * - If outer UDP checksum is non zero, then the hardware should + * compute and update it. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_OT_IP_CHKSUM UINT32_C(0x20) + /* + * If set to '1', then the RoCE ICRC will be appended to the + * packet. Packet must be a valid RoCE format packet. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_ROCE_CRC UINT32_C(0x100) + /* + * If set to '1', then the FCoE CRC will be appended to the + * packet. Packet must be a valid FCoE format packet. + */ + #define SQ_RAWQP1SEND_V3_LFLAGS_FCOE_CRC UINT32_C(0x200) + /* + * This value selects a CFA action to perform on the packet. + * Set this value to zero if no CFA action is desired. + * + * This value must be valid on the first BD of a packet. + */ + uint16_t cfa_action; + /* + * This value selects a CFA action to perform on the packet. + * Set this value to zero if no CFA action is desired. + * + * This value must be valid on the first BD of a packet. + */ + uint16_t cfa_action_high; + /* + * This value selects bits 25:16 of the CFA action to perform on + * the packet. See the cfa_action field for more information. + */ + #define SQ_RAWQP1SEND_V3_CFA_ACTION_HIGH_MASK UINT32_C(0x3ff) + #define SQ_RAWQP1SEND_V3_CFA_ACTION_HIGH_SFT 0 + uint16_t reserved_2; + /* + * This value is action meta-data that defines CFA edit operations + * that are done in addition to any action editing. + */ + uint32_t cfa_meta; + /* When key=1, This is the VLAN tag VID value. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_VID_MASK UINT32_C(0xfff) + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_VID_SFT 0 + /* When key=1, This is the VLAN tag DE value. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_DE UINT32_C(0x1000) + /* When key=1, This is the VLAN tag PRI value. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000) + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_PRI_SFT 13 + /* When key=1, This is the VLAN tag TPID select value. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000) + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_SFT 16 + /* 0x88a8 */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16) + /* 0x8100 */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16) + /* 0x9100 */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16) + /* 0x9200 */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16) + /* 0x9300 */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16) + /* Value programmed in CFA VLANTPID register. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16) + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_LAST SQ_RAWQP1SEND_V3_CFA_META_VLAN_TPID_TPIDCFG + /* When key=1, This is the VLAN tag TPID select value. */ + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000) + #define SQ_RAWQP1SEND_V3_CFA_META_VLAN_RESERVED_SFT 19 + /* + * This field identifies the type of edit to be performed + * on the packet. + * + * This value must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_V3_CFA_META_KEY_MASK UINT32_C(0xf0000000) + #define SQ_RAWQP1SEND_V3_CFA_META_KEY_SFT 28 + /* No editing */ + #define SQ_RAWQP1SEND_V3_CFA_META_KEY_NONE (UINT32_C(0x0) << 28) + /* + * - meta[17:16] - TPID select value (0 = 0x8100). + * - meta[15:12] - PRI/DE value. + * - meta[11:0] - VID value. + */ + #define SQ_RAWQP1SEND_V3_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28) + #define SQ_RAWQP1SEND_V3_CFA_META_KEY_LAST SQ_RAWQP1SEND_V3_CFA_META_KEY_VLAN_TAG + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_RAWQP1SEND_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_RAWQP1SEND_V3_TIMESTAMP_SFT 0 + uint64_t reserved_3; + /* + * When inline=0, then this area is filled with from 1 to 6 SGEs + * based on the wqe_size field. + * + * When inline=1, this area is filled with payload data for the + * send. Length of data is described in the inline_length field. + * Bits [7:0] of word 0 hold the first byte to go out on the wire. + */ + uint32_t data[24]; +} sq_rawqp1send_v3_t, *psq_rawqp1send_v3_t; + +/* SQ WQE V3 structure for Raw Ethernet and QP1 SQs. */ +/* sq_rawqp1send_hdr_v3 (size:256b/32B) */ + +typedef struct sq_rawqp1send_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* RawEth/QP1 Send V3 */ + #define SQ_RAWQP1SEND_HDR_V3_WQE_TYPE_RAWQP1SEND_V3 UINT32_C(0x1d) + #define SQ_RAWQP1SEND_HDR_V3_WQE_TYPE_LAST SQ_RAWQP1SEND_HDR_V3_WQE_TYPE_RAWQP1SEND_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + * + * This flag must be zero for a QP1 send. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_RAWQP1SEND_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_RAWQP1SEND_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_RAWQP1SEND_HDR_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_RAWQP1SEND_HDR_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_RAWQP1SEND_HDR_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * All bits in this field must be valid on the first BD of a packet. + * Their value on other BDs of the packet will be ignored. + */ + uint16_t lflags; + /* + * If set to 1, the controller replaces the TCP/UPD checksum + * fields of normal TCP/UPD checksum, or the inner TCP/UDP + * checksum field of the encapsulated TCP/UDP packets with the + * hardware calculated TCP/UDP checksum for the packet associated + * with this descriptor. + * + * This bit must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) + /* + * If set to 1, the controller replaces the IP checksum of the + * normal packets, or the inner IP checksum of the encapsulated + * packets with the hardware calculated IP checksum for the + * packet associated with this descriptor. + * + * This bit must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_IP_CHKSUM UINT32_C(0x2) + /* + * If set to 1, the controller will not append an Ethernet CRC + * to the end of the frame. + * + * This bit must be valid on the first BD of a packet. + * + * Packet must be 64B or longer when this flag is set. It is not + * useful to use this bit with any form of TX offload such as + * CSO or LSO. The intent is that the packet from the host already + * has a valid Ethernet CRC on the packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_NOCRC UINT32_C(0x4) + /* + * If set to 1, The controller replaces the tunnel IP checksum + * field with hardware calculated IP checksum for the IP header + * of the packet associated with this descriptor. In case of + * VXLAN, the controller also replaces the outer header UDP + * checksum with hardware calculated UDP checksum for the packet + * associated with this descriptor. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) + /* + * If set to 1, The controller replaces the Outer-tunnel IP + * checksum field with hardware calculated IP checksum for the IP + * header of the packet associated with this descriptor. + * + * For outer UDP checksum, it will be the following behavior for + * all cases independent of settings of inner LSO and checksum + * offload BD flags: + * + * - If outer UDP checksum is 0, then do not update it. + * - If outer UDP checksum is non zero, then the hardware should + * compute and update it. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_OT_IP_CHKSUM UINT32_C(0x20) + /* + * If set to '1', then the RoCE ICRC will be appended to the + * packet. Packet must be a valid RoCE format packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_ROCE_CRC UINT32_C(0x100) + /* + * If set to '1', then the FCoE CRC will be appended to the + * packet. Packet must be a valid FCoE format packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_LFLAGS_FCOE_CRC UINT32_C(0x200) + /* + * This value selects a CFA action to perform on the packet. + * Set this value to zero if no CFA action is desired. + * + * This value must be valid on the first BD of a packet. + */ + uint16_t cfa_action; + /* + * This value selects a CFA action to perform on the packet. + * Set this value to zero if no CFA action is desired. + * + * This value must be valid on the first BD of a packet. + */ + uint16_t cfa_action_high; + /* + * This value selects bits 25:16 of the CFA action to perform on + * the packet. See the cfa_action field for more information. + */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_ACTION_HIGH_MASK UINT32_C(0x3ff) + #define SQ_RAWQP1SEND_HDR_V3_CFA_ACTION_HIGH_SFT 0 + uint16_t reserved_2; + /* + * This value is action meta-data that defines CFA edit operations + * that are done in addition to any action editing. + */ + uint32_t cfa_meta; + /* When key=1, This is the VLAN tag VID value. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_VID_MASK UINT32_C(0xfff) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_VID_SFT 0 + /* When key=1, This is the VLAN tag DE value. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_DE UINT32_C(0x1000) + /* When key=1, This is the VLAN tag PRI value. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_PRI_SFT 13 + /* When key=1, This is the VLAN tag TPID select value. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_SFT 16 + /* 0x88a8 */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16) + /* 0x8100 */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16) + /* 0x9100 */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16) + /* 0x9200 */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16) + /* 0x9300 */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16) + /* Value programmed in CFA VLANTPID register. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_LAST SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_TPID_TPIDCFG + /* When key=1, This is the VLAN tag TPID select value. */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_VLAN_RESERVED_SFT 19 + /* + * This field identifies the type of edit to be performed + * on the packet. + * + * This value must be valid on the first BD of a packet. + */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_MASK UINT32_C(0xf0000000) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_SFT 28 + /* No editing */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_NONE (UINT32_C(0x0) << 28) + /* + * - meta[17:16] - TPID select value (0 = 0x8100). + * - meta[15:12] - PRI/DE value. + * - meta[11:0] - VID value. + */ + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28) + #define SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_LAST SQ_RAWQP1SEND_HDR_V3_CFA_META_KEY_VLAN_TAG + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_RAWQP1SEND_HDR_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_RAWQP1SEND_HDR_V3_TIMESTAMP_SFT 0 + uint64_t reserved_3; +} sq_rawqp1send_hdr_v3_t, *psq_rawqp1send_hdr_v3_t; + +/* SQ Send WQE V3 for UD SQs. */ +/* sq_udsend_v3 (size:1024b/128B) */ + +typedef struct sq_udsend_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * UD Send V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_UDSEND_V3_WQE_TYPE_UDSEND_V3 UINT32_C(0x13) + /* + * UD Send with Immediate V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_UDSEND_V3_WQE_TYPE_UDSEND_W_IMMED_V3 UINT32_C(0x14) + #define SQ_UDSEND_V3_WQE_TYPE_LAST SQ_UDSEND_V3_WQE_TYPE_UDSEND_W_IMMED_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_UDSEND_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_UDSEND_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_UDSEND_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + */ + #define SQ_UDSEND_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_UDSEND_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_UDSEND_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_UDSEND_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_UDSEND_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_UDSEND_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_UDSEND_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_UDSEND_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Immediate value that will be sent with ImmDt header if wqe_type is + * UD Send with Immediate. + */ + uint32_t imm_data; + /* + * When in the SQ of a UD QP, indicates the q_key to be used in + * the transmitted packet. However, if the most significant bit + * of this field is set, then the q_key will be taken from QP + * context, rather than from this field. + * + * When in the SQ of a non-UD QP, this field is reserved and + * should be filled with zeros. + */ + uint32_t q_key; + /* + * When in the SQ of a UD QP, indicates the destination QP to be + * used in the transmitted packet. + * + * When in the SQ of a non-UD QP, this field is reserved and + * should be filled with zeros. + */ + uint32_t dst_qp; + #define SQ_UDSEND_V3_DST_QP_MASK UINT32_C(0xffffff) + #define SQ_UDSEND_V3_DST_QP_SFT 0 + uint32_t avid; + /* + * If the serv_type is 'UD', then this field supplies the AVID + * (Address Vector ID). + */ + #define SQ_UDSEND_V3_AVID_MASK UINT32_C(0x3ff) + #define SQ_UDSEND_V3_AVID_SFT 0 + uint32_t reserved2; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_UDSEND_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_UDSEND_V3_TIMESTAMP_SFT 0 + /* + * When inline=0, then this area is filled with from 1 to 30 SGEs + * based on the wqe_size field. + * + * When inline=1, this area is filled with payload data for the + * send. Length of data is described in the inline_length field. + * Bits [7:0] of word 0 hold the first byte to go out on the wire. + */ + uint32_t data[24]; +} sq_udsend_v3_t, *psq_udsend_v3_t; + +/* SQ WQE V3 header for UD SQs. */ +/* sq_udsend_hdr_v3 (size:256b/32B) */ + +typedef struct sq_udsend_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * UD Send V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_UDSEND_HDR_V3_WQE_TYPE_UDSEND_V3 UINT32_C(0x13) + /* + * UD Send with Immediate V3 + * + * Allowed only on unreliable datagram (UD) SQs. + */ + #define SQ_UDSEND_HDR_V3_WQE_TYPE_UDSEND_W_IMMED_V3 UINT32_C(0x14) + #define SQ_UDSEND_HDR_V3_WQE_TYPE_LAST SQ_UDSEND_HDR_V3_WQE_TYPE_UDSEND_W_IMMED_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled completion + * the controller should not generate a CQE unless there was + * an error. This refers to the CQE on the sender side. (The se + * flag refers to the receiver side). + */ + #define SQ_UDSEND_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic WQEs + * on the SQ before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all + * previous SQ's WQEs before executing this WQE. + * + * This flag must be zero for a UD send. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event flag. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, i.e. + * CNQE. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ in the data + * area of this WQE. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_UDSEND_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_UDSEND_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_UDSEND_HDR_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_UDSEND_HDR_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_UDSEND_HDR_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Immediate value that will be sent with ImmDt header if wqe_type is + * UD Send with Immediate. + */ + uint32_t imm_data; + /* + * When in the SQ of a UD QP, indicates the q_key to be used in + * the transmitted packet. However, if the most significant bit + * of this field is set, then the q_key will be taken from QP + * context, rather than from this field. + * + * When in the SQ of a non-UD QP, this field is reserved and + * should be filled with zeros. + */ + uint32_t q_key; + /* + * When in the SQ of a UD QP, indicates the destination QP to be + * used in the transmitted packet. + * + * When in the SQ of a non-UD QP, this field is reserved and + * should be filled with zeros. + */ + uint32_t dst_qp; + #define SQ_UDSEND_HDR_V3_DST_QP_MASK UINT32_C(0xffffff) + #define SQ_UDSEND_HDR_V3_DST_QP_SFT 0 + uint32_t avid; + /* + * If the serv_type is 'UD', then this field supplies the AVID + * (Address Vector ID). + */ + #define SQ_UDSEND_HDR_V3_AVID_MASK UINT32_C(0x3ff) + #define SQ_UDSEND_HDR_V3_AVID_SFT 0 + uint32_t reserved2; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_UDSEND_HDR_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_UDSEND_HDR_V3_TIMESTAMP_SFT 0 +} sq_udsend_hdr_v3_t, *psq_udsend_hdr_v3_t; + +/* SQ RDMA WQE V3 for RC SQs. */ +/* sq_rdma_v3 (size:1024b/128B) */ + +typedef struct sq_rdma_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * RDMA Write V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_V3_WQE_TYPE_WRITE_WQE_V3 UINT32_C(0x15) + /* + * RDMA Write with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_V3_WQE_TYPE_WRITE_W_IMMED_V3 UINT32_C(0x16) + /* + * RDMA Read V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_V3_WQE_TYPE_READ_WQE_V3 UINT32_C(0x17) + #define SQ_RDMA_V3_WQE_TYPE_LAST SQ_RDMA_V3_WQE_TYPE_READ_WQE_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_RDMA_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_RDMA_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_RDMA_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, + * i.e. CNQE. + */ + #define SQ_RDMA_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ following + * this WQE. This bit may be 1 only for write operations. + */ + #define SQ_RDMA_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_RDMA_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_RDMA_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_RDMA_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_RDMA_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_RDMA_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_RDMA_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Immediate data - valid for RDMA Write with immediate and + * causes the controller to add immDt header with this value + */ + uint32_t imm_data; + uint32_t reserved2; + /* Remote VA sent to the destination QP */ + uint64_t remote_va; + /* + * R_Key provided by remote node when the connection was + * established and placed in the RETH header. It identify the + * MRW on the remote host + */ + uint32_t remote_key; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_RDMA_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_RDMA_V3_TIMESTAMP_SFT 0 + /* + * When inline=0, then this area is filled with from 1 to 30 SGEs + * based on the wqe_size field. + * + * When inline=1, this area is filled with payload data for the send. + * Length of data is described in the inline_length field. Bits [7:0] + * of word 0 hold the first byte to go out on the wire. + */ + uint32_t data[24]; +} sq_rdma_v3_t, *psq_rdma_v3_t; + +/* SQ RDMA WQE V3 header for RC SQs. */ +/* sq_rdma_hdr_v3 (size:256b/32B) */ + +typedef struct sq_rdma_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * RDMA Write V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_HDR_V3_WQE_TYPE_WRITE_WQE_V3 UINT32_C(0x15) + /* + * RDMA Write with Immediate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_HDR_V3_WQE_TYPE_WRITE_W_IMMED_V3 UINT32_C(0x16) + /* + * RDMA Read V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_RDMA_HDR_V3_WQE_TYPE_READ_WQE_V3 UINT32_C(0x17) + #define SQ_RDMA_HDR_V3_WQE_TYPE_LAST SQ_RDMA_HDR_V3_WQE_TYPE_READ_WQE_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_RDMA_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_RDMA_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_RDMA_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, + * i.e. CNQE. + */ + #define SQ_RDMA_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * Indicate that inline data is posted to the SQ following + * this WQE. This bit may be 1 only for write operations. + */ + #define SQ_RDMA_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * If set to 1, then the timestamp from the WQE is used. If + * cleared to 0, then TWE provides the timestamp. + */ + #define SQ_RDMA_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_RDMA_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The number of 16 bytes chunks of data including this first + * word of the request that are a valid part of the request. The + * valid 16 bytes units other than the WQE structure can be + * SGEs (Scatter Gather Elements) OR inline data. + * + * This field shall never exceed 32 for WQEs of this type. + */ + #define SQ_RDMA_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_RDMA_HDR_V3_WQE_SIZE_SFT 0 + uint8_t inline_length; + /* + * When inline flag is '1', this field determines the number of + * bytes that are valid in the last 16B unit of the inline WQE. + * Zero means all 16 bytes are valid. One means only bits 7:0 of + * the last 16B unit are valid. This means the total size of the + * inline data is determined by a combination of the wqe_size field + * and this inline_length field. + * + * `inline_size = ((wqe_size - 1) * 16) - data_offset_in_bytes + + * ((inline_length == 0 ) ? 16 : inline_length) + * + * Where data_offset_in_bytes is the offset within the WQE where + * the data field starts. + * + * Note that this field is not applicable for zero-length inline + * WQEs. + */ + #define SQ_RDMA_HDR_V3_INLINE_LENGTH_MASK UINT32_C(0xf) + #define SQ_RDMA_HDR_V3_INLINE_LENGTH_SFT 0 + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Immediate data - valid for RDMA Write with immediate and + * causes the controller to add immDt header with this value + */ + uint32_t imm_data; + uint32_t reserved2; + /* Remote VA sent to the destination QP */ + uint64_t remote_va; + /* + * R_Key provided by remote node when the connection was + * established and placed in the RETH header. It identify the + * MRW on the remote host + */ + uint32_t remote_key; + uint32_t timestamp; + /* + * This field specifies a 24-bit timestamp that can be passed + * down the TX path and optionally logged in the TXP timestamp + * histogram. + */ + #define SQ_RDMA_HDR_V3_TIMESTAMP_MASK UINT32_C(0xffffff) + #define SQ_RDMA_HDR_V3_TIMESTAMP_SFT 0 +} sq_rdma_hdr_v3_t, *psq_rdma_hdr_v3_t; + +/* SQ Atomic V3 WQE for RC SQs. */ +/* sq_atomic_v3 (size:448b/56B) */ + +typedef struct sq_atomic_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Atomic Compare/Swap V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_ATOMIC_V3_WQE_TYPE_ATOMIC_CS_V3 UINT32_C(0x18) + /* + * Atomic Fetch/Add V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_ATOMIC_V3_WQE_TYPE_ATOMIC_FA_V3 UINT32_C(0x19) + #define SQ_ATOMIC_V3_WQE_TYPE_LAST SQ_ATOMIC_V3_WQE_TYPE_ATOMIC_FA_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_ATOMIC_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_ATOMIC_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_ATOMIC_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, + * i.e. CNQE. + */ + #define SQ_ATOMIC_V3_FLAGS_SE UINT32_C(0x8) + /* NA for this WQE */ + #define SQ_ATOMIC_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * The atomic WQE does not have a timestamp field, so this field is + * ignored and should be zero. + */ + #define SQ_ATOMIC_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_ATOMIC_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Atomic WQE, this field will always have a value of 4. + */ + #define SQ_ATOMIC_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_ATOMIC_V3_WQE_SIZE_SFT 0 + uint8_t reserved1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * R_Key provided by remote node when the connection was + * established and placed in the AETH header. It identifies the + * MRW on the remote host. + */ + uint32_t remote_key; + uint32_t reserved2; + /* Remote VA sent to the destination QP */ + uint64_t remote_va; + /* + * For compare/swap, this is the data value to be placed in the + * remote host at the specified remote_VA if the comparison succeeds. + * + * For fetch/add, this is the value to be added to the data in the + * remote host at the specified remote_VA. + */ + uint64_t swap_data; + /* + * For compare/swap, this is the data value to be compared with the + * value in the remote host at the specified remote_VA. + * + * This field is not used for fetch/add. + */ + uint64_t cmp_data; + /* + * The virtual address in local memory or a physical address when + * l_key value is a reserved value of a physical address. Driver + * configures this value in the chip and the chip compares l_key in + * SGEs with that reserved value, if equal it access the physical + * address specified. The chip however MUST verify that the QP allows + * the use reserved key. + */ + uint64_t va_or_pa; + /* + * Local Key associated with this registered MR; The 24 msb of the + * key used to index the MRW Table and the 8 lsb are compared with + * the 8 bits key part stored in the MRWC. The PBL in the MRW Context + * is used to translate the above VA to physical address. + */ + uint32_t l_key; + /* + * Size of SGE in bytes; Based on page size of the system the chip + * knows how many entries are in the PBL + * + * This field must have a value of 8 for an Atomic WQE. + */ + uint32_t size; +} sq_atomic_v3_t, *psq_atomic_v3_t; + +/* SQ Atomic WQE V3 header for RC SQs. */ +/* sq_atomic_hdr_v3 (size:320b/40B) */ + +typedef struct sq_atomic_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Atomic Compare/Swap V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_ATOMIC_HDR_V3_WQE_TYPE_ATOMIC_CS_V3 UINT32_C(0x18) + /* + * Atomic Fetch/Add V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_ATOMIC_HDR_V3_WQE_TYPE_ATOMIC_FA_V3 UINT32_C(0x19) + #define SQ_ATOMIC_HDR_V3_WQE_TYPE_LAST SQ_ATOMIC_HDR_V3_WQE_TYPE_ATOMIC_FA_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * Solicit event. Indication sent in BTH header to the + * receiver to generate a Completion Event Notification, + * i.e. CNQE. + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* NA for this WQE */ + #define SQ_ATOMIC_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * The atomic WQE does not have a timestamp field, so this field is + * ignored and should be zero. + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_ATOMIC_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Atomic WQE, this field will always have a value of 4. + */ + #define SQ_ATOMIC_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_ATOMIC_HDR_V3_WQE_SIZE_SFT 0 + uint8_t reserved1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * R_Key provided by remote node when the connection was + * established and placed in the AETH header. It identifies the + * MRW on the remote host. + */ + uint32_t remote_key; + uint32_t reserved2; + /* Remote VA sent to the destination QP */ + uint64_t remote_va; + /* + * For compare/swap, this is the data value to be placed in the + * remote host at the specified remote_VA if the comparison succeeds. + * + * For fetch/add, this is the value to be added to the data in the + * remote host at the specified remote_VA. + */ + uint64_t swap_data; + /* + * For compare/swap, this is the data value to be compared with the + * value in the remote host at the specified remote_VA. + * + * This field is not used for fetch/add. + */ + uint64_t cmp_data; +} sq_atomic_hdr_v3_t, *psq_atomic_hdr_v3_t; + +/* SQ Local Invalidate WQE V3 for RC SQs. */ +/* sq_localinvalidate_v3 (size:128b/16B) */ + +typedef struct sq_localinvalidate_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Local Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_LOCALINVALIDATE_V3_WQE_TYPE_LOCAL_INVALID_V3 UINT32_C(0x1a) + #define SQ_LOCALINVALIDATE_V3_WQE_TYPE_LAST SQ_LOCALINVALIDATE_V3_WQE_TYPE_LOCAL_INVALID_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_LOCALINVALIDATE_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Local Invalidate WQE, this field will always have + * a value of 1. + */ + #define SQ_LOCALINVALIDATE_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_LOCALINVALIDATE_V3_WQE_SIZE_SFT 0 + uint8_t reserved1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * The local key for the MR/W to invalidate; 24 msb of the key + * are used to index the MRW table, 8 lsb are compared with the + * 8 bit key in the MRWC + */ + uint32_t inv_l_key; + uint32_t reserved2; +} sq_localinvalidate_v3_t, *psq_localinvalidate_v3_t; + +/* SQ Local Invalidate WQE V3 header for RC SQs. */ +/* sq_localinvalidate_hdr_v3 (size:128b/16B) */ + +typedef struct sq_localinvalidate_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Local Invalidate V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_WQE_TYPE_LOCAL_INVALID_V3 UINT32_C(0x1a) + #define SQ_LOCALINVALIDATE_HDR_V3_WQE_TYPE_LAST SQ_LOCALINVALIDATE_HDR_V3_WQE_TYPE_LOCAL_INVALID_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Local Invalidate WQE, this field will always have + * a value of 1. + */ + #define SQ_LOCALINVALIDATE_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_LOCALINVALIDATE_HDR_V3_WQE_SIZE_SFT 0 + uint8_t reserved1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * The local key for the MR/W to invalidate; 24 msb of the key + * are used to index the MRW table, 8 lsb are compared with the + * 8 bit key in the MRWC + */ + uint32_t inv_l_key; + uint32_t reserved2; +} sq_localinvalidate_hdr_v3_t, *psq_localinvalidate_hdr_v3_t; + +/* + * SQ FR-PMR WQE V3 for RC SQs. + * + * The FR-PMR WQE must be padded to 3 slots (48 bytes) in the SQ, even + * though the final 8 bytes are not shown here. + */ +/* sq_fr_pmr_v3 (size:320b/40B) */ + +typedef struct sq_fr_pmr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * FR-PMR (Fast Register Physical Memory Region) V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_FR_PMR_V3_WQE_TYPE_FR_PMR_V3 UINT32_C(0x1b) + #define SQ_FR_PMR_V3_WQE_TYPE_LAST SQ_FR_PMR_V3_WQE_TYPE_FR_PMR_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_FR_PMR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_FR_PMR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_FR_PMR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_FR_PMR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size_zero_based; + /* + * The size of the WQE in units of 16B chunks. + * + * For the FR-PMR WQE, this field will always have a value of 3. + */ + #define SQ_FR_PMR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_FR_PMR_V3_WQE_SIZE_SFT 0 + /* + * If this is set, the PMR will be zero-based. If clear, the PMR + * will be non-zero-based. + */ + #define SQ_FR_PMR_V3_ZERO_BASED UINT32_C(0x40) + /* + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is + * not allowed. + */ + uint8_t access_cntl; + /* Local Write Access */ + #define SQ_FR_PMR_V3_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) + /* Remote Read Access */ + #define SQ_FR_PMR_V3_ACCESS_CNTL_REMOTE_READ UINT32_C(0x2) + /* Remote Write Access */ + #define SQ_FR_PMR_V3_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) + /* Remote Atomic Access */ + #define SQ_FR_PMR_V3_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) + /* Window Binding Allowed */ + #define SQ_FR_PMR_V3_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Local Key; 24 msb of the key are used to index the MRW + * table, 8 lsb are assigned to the 8 bit key_lsb field in + * the MRWC. + */ + uint32_t l_key; + uint16_t page_size_log; + /* + * This value controls the page size for leaf memory pages in + * a PBL. While many page sizes are supported only the following + * should be tested - 4k, 8k, 64k, 256k, 1m, 2m, 4m, 1g + */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_MASK UINT32_C(0x1f) + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_SFT 0 + /* Page size is 4KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_4K UINT32_C(0x0) + /* Page size is 8KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_8K UINT32_C(0x1) + /* Page size is 16KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_16K UINT32_C(0x2) + /* Page size is 32KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_32K UINT32_C(0x3) + /* Page size is 64KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_64K UINT32_C(0x4) + /* Page size is 128KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_128K UINT32_C(0x5) + /* Page size is 256KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_256K UINT32_C(0x6) + /* Page size is 512KB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_512K UINT32_C(0x7) + /* Page size is 1MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_1M UINT32_C(0x8) + /* Page size is 2MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_2M UINT32_C(0x9) + /* Page size is 4MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_4M UINT32_C(0xa) + /* Page size is 8MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_8M UINT32_C(0xb) + /* Page size is 16MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_16M UINT32_C(0xc) + /* Page size is 32MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_32M UINT32_C(0xd) + /* Page size is 64MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_64M UINT32_C(0xe) + /* Page size is 128MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_128M UINT32_C(0xf) + /* Page size is 256MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_256M UINT32_C(0x10) + /* Page size is 512MB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_512M UINT32_C(0x11) + /* Page size is 1GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_1G UINT32_C(0x12) + /* Page size is 2GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_2G UINT32_C(0x13) + /* Page size is 4GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_4G UINT32_C(0x14) + /* Page size is 8GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_8G UINT32_C(0x15) + /* Page size is 16GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_16G UINT32_C(0x16) + /* Page size is 32GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_32G UINT32_C(0x17) + /* Page size is 64GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_64G UINT32_C(0x18) + /* Page size is 128GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_128G UINT32_C(0x19) + /* Page size is 256GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_256G UINT32_C(0x1a) + /* Page size is 512GB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_512G UINT32_C(0x1b) + /* Page size is 1TB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_1T UINT32_C(0x1c) + /* Page size is 2TB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_2T UINT32_C(0x1d) + /* Page size is 4TB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_4T UINT32_C(0x1e) + /* Page size is 8TB. */ + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_8T UINT32_C(0x1f) + #define SQ_FR_PMR_V3_PAGE_SIZE_LOG_LAST SQ_FR_PMR_V3_PAGE_SIZE_LOG_PGSZ_8T + /* + * This value controls the page size for page table elements + * within a PBL. While many page sizes are supported only the + * following should be tested - 4k, 8k, 64k, 256k, 1m, 2m, 4m, 1g + */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_MASK UINT32_C(0x3e0) + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_SFT 5 + /* Page size is 4KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4K (UINT32_C(0x0) << 5) + /* Page size is 8KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8K (UINT32_C(0x1) << 5) + /* Page size is 16KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16K (UINT32_C(0x2) << 5) + /* Page size is 32KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32K (UINT32_C(0x3) << 5) + /* Page size is 64KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64K (UINT32_C(0x4) << 5) + /* Page size is 128KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128K (UINT32_C(0x5) << 5) + /* Page size is 256KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256K (UINT32_C(0x6) << 5) + /* Page size is 512KB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512K (UINT32_C(0x7) << 5) + /* Page size is 1MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1M (UINT32_C(0x8) << 5) + /* Page size is 2MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2M (UINT32_C(0x9) << 5) + /* Page size is 4MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4M (UINT32_C(0xa) << 5) + /* Page size is 8MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8M (UINT32_C(0xb) << 5) + /* Page size is 16MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16M (UINT32_C(0xc) << 5) + /* Page size is 32MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32M (UINT32_C(0xd) << 5) + /* Page size is 64MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64M (UINT32_C(0xe) << 5) + /* Page size is 128MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128M (UINT32_C(0xf) << 5) + /* Page size is 256MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256M (UINT32_C(0x10) << 5) + /* Page size is 512MB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512M (UINT32_C(0x11) << 5) + /* Page size is 1GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1G (UINT32_C(0x12) << 5) + /* Page size is 2GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2G (UINT32_C(0x13) << 5) + /* Page size is 4GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4G (UINT32_C(0x14) << 5) + /* Page size is 8GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8G (UINT32_C(0x15) << 5) + /* Page size is 16GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16G (UINT32_C(0x16) << 5) + /* Page size is 32GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32G (UINT32_C(0x17) << 5) + /* Page size is 64GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64G (UINT32_C(0x18) << 5) + /* Page size is 128GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128G (UINT32_C(0x19) << 5) + /* Page size is 256GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256G (UINT32_C(0x1a) << 5) + /* Page size is 512GB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512G (UINT32_C(0x1b) << 5) + /* Page size is 1TB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1T (UINT32_C(0x1c) << 5) + /* Page size is 2TB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2T (UINT32_C(0x1d) << 5) + /* Page size is 4TB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4T (UINT32_C(0x1e) << 5) + /* Page size is 8TB. */ + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8T (UINT32_C(0x1f) << 5) + #define SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_LAST SQ_FR_PMR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8T + /* Number of levels of PBL for translation */ + #define SQ_FR_PMR_V3_NUMLEVELS_MASK UINT32_C(0xc00) + #define SQ_FR_PMR_V3_NUMLEVELS_SFT 10 + /* + * A zero level PBL means that the VA is the physical address + * used for the operation. No translation is done by the PTU. + */ + #define SQ_FR_PMR_V3_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 10) + /* + * A one layer translation is provided between the logical and + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical + * pages. + */ + #define SQ_FR_PMR_V3_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 10) + /* + * A two layer translation is provided between the logical and + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size + * physical pages that contain PBE values that point to actual + * physical pages. + */ + #define SQ_FR_PMR_V3_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 10) + #define SQ_FR_PMR_V3_NUMLEVELS_LAST SQ_FR_PMR_V3_NUMLEVELS_LAYER2 + uint16_t reserved; + /* Local Virtual Address */ + uint64_t va; + /* Length in bytes of registered MR */ + uint64_t length; + /* Pointer to the PBL, or PDL depending on number of levels */ + uint64_t pbl_ptr; +} sq_fr_pmr_v3_t, *psq_fr_pmr_v3_t; + +/* SQ FR-PMR WQE V3 header for RC SQs. */ +/* sq_fr_pmr_hdr_v3 (size:320b/40B) */ + +typedef struct sq_fr_pmr_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * FR-PMR (Fast Register Physical Memory Region) V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_FR_PMR_HDR_V3_WQE_TYPE_FR_PMR_V3 UINT32_C(0x1b) + #define SQ_FR_PMR_HDR_V3_WQE_TYPE_LAST SQ_FR_PMR_HDR_V3_WQE_TYPE_FR_PMR_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_FR_PMR_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + /* */ + uint8_t wqe_size_zero_based; + /* + * The size of the WQE in units of 16B chunks. + * + * For the FR-PMR WQE, this field will always have a value of 3. + */ + #define SQ_FR_PMR_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_FR_PMR_HDR_V3_WQE_SIZE_SFT 0 + /* + * If this is set, the PMR will be zero-based. If clear, the PMR + * will be non-zero-based. + */ + #define SQ_FR_PMR_HDR_V3_ZERO_BASED UINT32_C(0x40) + /* + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is + * not allowed. + */ + uint8_t access_cntl; + /* Local Write Access */ + #define SQ_FR_PMR_HDR_V3_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) + /* Remote Read Access */ + #define SQ_FR_PMR_HDR_V3_ACCESS_CNTL_REMOTE_READ UINT32_C(0x2) + /* Remote Write Access */ + #define SQ_FR_PMR_HDR_V3_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) + /* Remote Atomic Access */ + #define SQ_FR_PMR_HDR_V3_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) + /* Window Binding Allowed */ + #define SQ_FR_PMR_HDR_V3_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * Local Key; 24 msb of the key are used to index the MRW + * table, 8 lsb are assigned to the 8 bit key_lsb field in + * the MRWC. + */ + uint32_t l_key; + uint16_t page_size_log; + /* + * This value controls the page size for leaf memory pages in + * a PBL. While many page sizes are supported only the following + * should be tested - 4k, 8k, 64k, 256k, 1m, 2m, 4m, 1g + */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_MASK UINT32_C(0x1f) + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_SFT 0 + /* Page size is 4KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_4K UINT32_C(0x0) + /* Page size is 8KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_8K UINT32_C(0x1) + /* Page size is 16KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_16K UINT32_C(0x2) + /* Page size is 32KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_32K UINT32_C(0x3) + /* Page size is 64KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_64K UINT32_C(0x4) + /* Page size is 128KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_128K UINT32_C(0x5) + /* Page size is 256KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_256K UINT32_C(0x6) + /* Page size is 512KB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_512K UINT32_C(0x7) + /* Page size is 1MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_1M UINT32_C(0x8) + /* Page size is 2MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_2M UINT32_C(0x9) + /* Page size is 4MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_4M UINT32_C(0xa) + /* Page size is 8MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_8M UINT32_C(0xb) + /* Page size is 16MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_16M UINT32_C(0xc) + /* Page size is 32MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_32M UINT32_C(0xd) + /* Page size is 64MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_64M UINT32_C(0xe) + /* Page size is 128MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_128M UINT32_C(0xf) + /* Page size is 256MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_256M UINT32_C(0x10) + /* Page size is 512MB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_512M UINT32_C(0x11) + /* Page size is 1GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_1G UINT32_C(0x12) + /* Page size is 2GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_2G UINT32_C(0x13) + /* Page size is 4GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_4G UINT32_C(0x14) + /* Page size is 8GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_8G UINT32_C(0x15) + /* Page size is 16GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_16G UINT32_C(0x16) + /* Page size is 32GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_32G UINT32_C(0x17) + /* Page size is 64GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_64G UINT32_C(0x18) + /* Page size is 128GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_128G UINT32_C(0x19) + /* Page size is 256GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_256G UINT32_C(0x1a) + /* Page size is 512GB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_512G UINT32_C(0x1b) + /* Page size is 1TB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_1T UINT32_C(0x1c) + /* Page size is 2TB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_2T UINT32_C(0x1d) + /* Page size is 4TB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_4T UINT32_C(0x1e) + /* Page size is 8TB. */ + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_8T UINT32_C(0x1f) + #define SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_LAST SQ_FR_PMR_HDR_V3_PAGE_SIZE_LOG_PGSZ_8T + /* + * This value controls the page size for page table elements + * within a PBL. While many page sizes are supported only the + * following should be tested - 4k, 8k, 64k, 256k, 1m, 2m, 4m, 1g + */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_MASK UINT32_C(0x3e0) + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_SFT 5 + /* Page size is 4KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4K (UINT32_C(0x0) << 5) + /* Page size is 8KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8K (UINT32_C(0x1) << 5) + /* Page size is 16KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16K (UINT32_C(0x2) << 5) + /* Page size is 32KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32K (UINT32_C(0x3) << 5) + /* Page size is 64KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64K (UINT32_C(0x4) << 5) + /* Page size is 128KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128K (UINT32_C(0x5) << 5) + /* Page size is 256KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256K (UINT32_C(0x6) << 5) + /* Page size is 512KB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512K (UINT32_C(0x7) << 5) + /* Page size is 1MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1M (UINT32_C(0x8) << 5) + /* Page size is 2MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2M (UINT32_C(0x9) << 5) + /* Page size is 4MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4M (UINT32_C(0xa) << 5) + /* Page size is 8MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8M (UINT32_C(0xb) << 5) + /* Page size is 16MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16M (UINT32_C(0xc) << 5) + /* Page size is 32MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32M (UINT32_C(0xd) << 5) + /* Page size is 64MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64M (UINT32_C(0xe) << 5) + /* Page size is 128MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128M (UINT32_C(0xf) << 5) + /* Page size is 256MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256M (UINT32_C(0x10) << 5) + /* Page size is 512MB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512M (UINT32_C(0x11) << 5) + /* Page size is 1GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1G (UINT32_C(0x12) << 5) + /* Page size is 2GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2G (UINT32_C(0x13) << 5) + /* Page size is 4GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4G (UINT32_C(0x14) << 5) + /* Page size is 8GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8G (UINT32_C(0x15) << 5) + /* Page size is 16GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_16G (UINT32_C(0x16) << 5) + /* Page size is 32GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_32G (UINT32_C(0x17) << 5) + /* Page size is 64GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_64G (UINT32_C(0x18) << 5) + /* Page size is 128GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_128G (UINT32_C(0x19) << 5) + /* Page size is 256GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_256G (UINT32_C(0x1a) << 5) + /* Page size is 512GB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_512G (UINT32_C(0x1b) << 5) + /* Page size is 1TB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_1T (UINT32_C(0x1c) << 5) + /* Page size is 2TB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_2T (UINT32_C(0x1d) << 5) + /* Page size is 4TB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_4T (UINT32_C(0x1e) << 5) + /* Page size is 8TB. */ + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8T (UINT32_C(0x1f) << 5) + #define SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_LAST SQ_FR_PMR_HDR_V3_PBL_PAGE_SIZE_LOG_PGSZ_8T + /* Number of levels of PBL for translation */ + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_MASK UINT32_C(0xc00) + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_SFT 10 + /* + * A zero level PBL means that the VA is the physical address + * used for the operation. No translation is done by the PTU. + */ + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_PHYSICAL (UINT32_C(0x0) << 10) + /* + * A one layer translation is provided between the logical and + * physical address. The PBL points to a physical page that + * contains PBE values that point to actual pg_size physical + * pages. + */ + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_LAYER1 (UINT32_C(0x1) << 10) + /* + * A two layer translation is provided between the logical and + * physical address. The PBL points to a physical page that + * contains PDE values that in turn point to pbl_pg_size + * physical pages that contain PBE values that point to actual + * physical pages. + */ + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_LAYER2 (UINT32_C(0x2) << 10) + #define SQ_FR_PMR_HDR_V3_NUMLEVELS_LAST SQ_FR_PMR_HDR_V3_NUMLEVELS_LAYER2 + uint16_t reserved; + /* Local Virtual Address */ + uint64_t va; + /* Length in bytes of registered MR */ + uint64_t length; + /* Pointer to the PBL, or PDL depending on number of levels */ + uint64_t pbl_ptr; +} sq_fr_pmr_hdr_v3_t, *psq_fr_pmr_hdr_v3_t; + +/* + * SQ Bind WQE V3. This WQE can perform either: + * * type1 "bind memory window", if mw_type==Type1 + * * type2 "post send bind memory window", if mw_type==Type2 + */ +/* sq_bind_v3 (size:256b/32B) */ + +typedef struct sq_bind_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Memory Bind V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BIND_V3_WQE_TYPE_BIND_V3 UINT32_C(0x1c) + #define SQ_BIND_V3_WQE_TYPE_LAST SQ_BIND_V3_WQE_TYPE_BIND_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_BIND_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_BIND_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_BIND_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_BIND_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + uint8_t wqe_size_zero_based_mw_type; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Bind WQE, this field will always have a value of 2. + */ + #define SQ_BIND_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_BIND_V3_WQE_SIZE_SFT 0 + /* + * If this bit is set, then the newly-bound memory window will be + * zero-based. If clear, then the newly-bound memory window will be + * non-zero-based. + */ + #define SQ_BIND_V3_ZERO_BASED UINT32_C(0x40) + /* + * If type1 is specified, then this WQE performs a "bind memory + * window" operation on a type1 window. If type2 is specified, then + * this WQE performs a "post send bind memory window" operation on a + * type2 window. + * + * Note that the bind WQE cannot change the type of the memory + * window. + * + * If a "bind memory window" operation is attempted on a memory + * window that was allocated as type2, then the bind will fail with + * an errored completion, as "bind memory window" is allowed only on + * type1 memory windows. + * + * Similarly, if a "post send bind memory window" operation is + * attempted on a memory window that was allocated as type1, then the + * bind will fail with an errored completions, as "post send bind + * memory window" is allowed only on type2 memory windows. + */ + #define SQ_BIND_V3_MW_TYPE UINT32_C(0x80) + /* Type 1 Bind Memory Window */ + #define SQ_BIND_V3__TYPE1 (UINT32_C(0x0) << 7) + /* Type 2 Post Send Bind Memory Window */ + #define SQ_BIND_V3__TYPE2 (UINT32_C(0x1) << 7) + #define SQ_BIND_V3__LAST SQ_BIND_V3__TYPE2 + /* + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is + * not allowed. + */ + uint8_t access_cntl; + /* + * Local Write Access. + * + * Local accesses are never allowed for memory windows, so this + * bit must always be zero in a bind WQE. If this bit is ever + * set, the bind will fail with an errored completion. + */ + #define SQ_BIND_V3_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) + /* Remote Read Access */ + #define SQ_BIND_V3_ACCESS_CNTL_REMOTE_READ UINT32_C(0x2) + /* + * Remote Write Access. + * + * Note that, if this bit is set, then the parent region to which + * the window is being bound must allow local writes. If this is not + * the case, then the bind will fail with an errored completion. + */ + #define SQ_BIND_V3_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) + /* + * Remote Atomic Access. + * + * Note that, if this bit is set, then the parent region to which + * the window is being bound must allow local writes. If this is not + * the case, then the bind will fail with an errored completion. + */ + #define SQ_BIND_V3_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) + /* + * Window Binding Allowed. + * + * It is never allowed to bind windows to windows, so this bit + * must always be zero in a bind WQE. If this bit is ever set, + * the bind will fail with an errored completion. + */ + #define SQ_BIND_V3_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * The L_Key of the parent MR; 24 msb of the key are used to + * index the MRW table, 8 lsb are compared with the 8 bit key + * in the MRWC. + */ + uint32_t parent_l_key; + /* + * Local Key; 24 msb of the key are used to index the memory + * window being bound in the MRW table, 8 lsb are assign to the + * 8 bit key_lsb field in the MRWC. + */ + uint32_t l_key; + /* Local Virtual Address */ + uint64_t va; + /* + * Length in bytes of registered MW; 40 bits as this is the max + * size of an MR/W + */ + uint64_t length; +} sq_bind_v3_t, *psq_bind_v3_t; + +/* + * SQ Bind WQE V3 header. This WQE can perform either: + * * type1 "bind memory window", if mw_type==Type1 + * * type2 "post send bind memory window", if mw_type==Type2 + */ +/* sq_bind_hdr_v3 (size:256b/32B) */ + +typedef struct sq_bind_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* + * Memory Bind V3 + * + * Allowed only on reliable connection (RC) SQs. + */ + #define SQ_BIND_HDR_V3_WQE_TYPE_BIND_V3 UINT32_C(0x1c) + #define SQ_BIND_HDR_V3_WQE_TYPE_LAST SQ_BIND_HDR_V3_WQE_TYPE_BIND_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_BIND_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_BIND_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + */ + #define SQ_BIND_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_BIND_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_BIND_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + uint8_t wqe_size_zero_based_mw_type; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Bind WQE, this field will always have a value of 2. + */ + #define SQ_BIND_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_BIND_HDR_V3_WQE_SIZE_SFT 0 + /* + * If this bit is set, then the newly-bound memory window will be + * zero-based. If clear, then the newly-bound memory window will be + * non-zero-based. + */ + #define SQ_BIND_HDR_V3_ZERO_BASED UINT32_C(0x40) + /* + * If type1 is specified, then this WQE performs a "bind memory + * window" operation on a type1 window. If type2 is specified, then + * this WQE performs a "post send bind memory window" operation on a + * type2 window. + * + * Note that the bind WQE cannot change the type of the memory + * window. + * + * If a "bind memory window" operation is attempted on a memory + * window that was allocated as type2, then the bind will fail with + * an errored completion, as "bind memory window" is allowed only on + * type1 memory windows. + * + * Similarly, if a "post send bind memory window" operation is + * attempted on a memory window that was allocated as type1, then the + * bind will fail with an errored completions, as "post send bind + * memory window" is allowed only on type2 memory windows. + */ + #define SQ_BIND_HDR_V3_MW_TYPE UINT32_C(0x80) + /* Type 1 Bind Memory Window */ + #define SQ_BIND_HDR_V3__TYPE1 (UINT32_C(0x0) << 7) + /* Type 2 Post Send Bind Memory Window */ + #define SQ_BIND_HDR_V3__TYPE2 (UINT32_C(0x1) << 7) + #define SQ_BIND_HDR_V3__LAST SQ_BIND_HDR_V3__TYPE2 + /* + * This is the new access control for the MR. '1' means + * the operation is allowed. '0' means operation is + * not allowed. + */ + uint8_t access_cntl; + /* + * Local Write Access. + * + * Local accesses are never allowed for memory windows, so this + * bit must always be zero in a bind WQE. If this bit is ever + * set, the bind will fail with an errored completion. + */ + #define SQ_BIND_HDR_V3_ACCESS_CNTL_LOCAL_WRITE UINT32_C(0x1) + /* Remote Read Access */ + #define SQ_BIND_HDR_V3_ACCESS_CNTL_REMOTE_READ UINT32_C(0x2) + /* + * Remote Write Access. + * + * Note that, if this bit is set, then the parent region to which + * the window is being bound must allow local writes. If this is not + * the case, then the bind will fail with an errored completion. + */ + #define SQ_BIND_HDR_V3_ACCESS_CNTL_REMOTE_WRITE UINT32_C(0x4) + /* + * Remote Atomic Access. + * + * Note that, if this bit is set, then the parent region to which + * the window is being bound must allow local writes. If this is not + * the case, then the bind will fail with an errored completion. + */ + #define SQ_BIND_HDR_V3_ACCESS_CNTL_REMOTE_ATOMIC UINT32_C(0x8) + /* + * Window Binding Allowed. + * + * It is never allowed to bind windows to windows, so this bit + * must always be zero in a bind WQE. If this bit is ever set, + * the bind will fail with an errored completion. + */ + #define SQ_BIND_HDR_V3_ACCESS_CNTL_WINDOW_BIND UINT32_C(0x10) + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* + * The L_Key of the parent MR; 24 msb of the key are used to + * index the MRW table, 8 lsb are compared with the 8 bit key + * in the MRWC. + */ + uint32_t parent_l_key; + /* + * Local Key; 24 msb of the key are used to index the memory + * window being bound in the MRW table, 8 lsb are assign to the + * 8 bit key_lsb field in the MRWC. + */ + uint32_t l_key; + /* Local Virtual Address */ + uint64_t va; + /* + * Length in bytes of registered MW; 40 bits as this is the max + * size of an MR/W + */ + uint64_t length; +} sq_bind_hdr_v3_t, *psq_bind_hdr_v3_t; + +/* + * This is the Change UDP Source Port WQE V3 structure. It is supported + * for both RC and UD QP's. + * + * It is recommended to set the uc_fence flag for this WQE, so that the + * source port does not change while there are unacknowledged packets. + */ +/* sq_change_udpsrcport_v3 (size:128b/16B) */ + +typedef struct sq_change_udpsrcport_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* Change UDP Source Port V3 */ + #define SQ_CHANGE_UDPSRCPORT_V3_WQE_TYPE_CHANGE_UDPSRCPORT_V3 UINT32_C(0x1e) + #define SQ_CHANGE_UDPSRCPORT_V3_WQE_TYPE_LAST SQ_CHANGE_UDPSRCPORT_V3_WQE_TYPE_CHANGE_UDPSRCPORT_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + * + * It is recommended to set this flag for Change UDP Source Port + * WQE's. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Change UDP Source Port WQE, this field will always have + * a value of 1. + */ + #define SQ_CHANGE_UDPSRCPORT_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_CHANGE_UDPSRCPORT_V3_WQE_SIZE_SFT 0 + uint8_t reserved_1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* The new value for the QP's UDP source port. */ + uint16_t udp_src_port; + uint16_t reserved_2; + uint32_t reserved_3; +} sq_change_udpsrcport_v3_t, *psq_change_udpsrcport_v3_t; + +/* SQ Change UDP Source Port WQE V3 header */ +/* sq_change_udpsrcport_hdr_v3 (size:128b/16B) */ + +typedef struct sq_change_udpsrcport_hdr_v3 { + /* This field defines the type of SQ WQE. */ + uint8_t wqe_type; + /* Change UDP Source Port V3 */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_WQE_TYPE_CHANGE_UDPSRCPORT_V3 UINT32_C(0x1e) + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_WQE_TYPE_LAST SQ_CHANGE_UDPSRCPORT_HDR_V3_WQE_TYPE_CHANGE_UDPSRCPORT_V3 + uint8_t flags; + /* + * Set if completion signaling is requested. If this bit is + * 0, and the SQ is configured to support Unsignaled + * completion the controller should not generate a CQE + * unless there was an error. This refers to CQE on the + * sender side (The se flag refers to the receiver side). + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_SIGNAL_COMP UINT32_C(0x1) + /* + * Indication to complete all previous RDMA Read or Atomic + * WQEs on the SQ before executing this WQE + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_RD_OR_ATOMIC_FENCE UINT32_C(0x2) + /* + * Unconditional fence. Indication to complete all previous + * SQ's WQEs before executing this WQE. + * + * It is recommended to set this flag for Change UDP Source Port + * WQE's. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_UC_FENCE UINT32_C(0x4) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_SE UINT32_C(0x8) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_INLINE UINT32_C(0x10) + /* + * This flag is not applicable and should be 0 for a local memory + * operation WQE. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_WQE_TS_EN UINT32_C(0x20) + /* + * When set to '1', this operation will cause a trace capture in + * each block it passes through. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_FLAGS_DEBUG_TRACE UINT32_C(0x40) + uint8_t wqe_size; + /* + * The size of the WQE in units of 16B chunks. + * + * For the Change UDP Source Port WQE, this field will always have + * a value of 1. + */ + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_WQE_SIZE_MASK UINT32_C(0x3f) + #define SQ_CHANGE_UDPSRCPORT_HDR_V3_WQE_SIZE_SFT 0 + uint8_t reserved_1; + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; + /* The new value for the QP's UDP source port. */ + uint16_t udp_src_port; + uint16_t reserved_2; + uint32_t reserved_3; +} sq_change_udpsrcport_hdr_v3_t, *psq_change_udpsrcport_hdr_v3_t; + /* RQ/SRQ WQE */ /* rq_wqe (size:1024b/128B) */ @@ -72641,7 +84514,7 @@ typedef struct rq_wqe { /* wqe_type is 8 b */ uint8_t wqe_type; /* - * RQ/SRQ WQE. This WQE is used for posting buffers on + * RQ/SRQ WQE. This WQE is used for posting buffers on * an RQ or SRQ. */ #define RQ_WQE_WQE_TYPE_RCV UINT32_C(0x80) @@ -72650,7 +84523,7 @@ typedef struct rq_wqe { uint8_t flags; /* * Specify the total number 16B chunks that make up the valid - * portion of the WQE. This includes the first chunk that is the + * portion of the WQE. This includes the first chunk that is the * WQE structure and up to 6 SGE structures. * * While the valid area is defined by the wqe_size field, the @@ -72682,7 +84555,7 @@ typedef struct rq_wqe_hdr { /* wqe_type is 8 b */ uint8_t wqe_type; /* - * RQ/SRQ WQE. This WQE is used for posting buffers on + * RQ/SRQ WQE. This WQE is used for posting buffers on * an RQ or SRQ. */ #define RQ_WQE_HDR_WQE_TYPE_RCV UINT32_C(0x80) @@ -72691,7 +84564,7 @@ typedef struct rq_wqe_hdr { uint8_t flags; /* * Specify the total number 16B chunks that make up the valid - * portion of the WQE. This includes the first chunk that is the + * portion of the WQE. This includes the first chunk that is the * WQE structure and up to 6 SGE structures. * * While the valid area is defined by the wqe_size field, the @@ -72711,6 +84584,65 @@ typedef struct rq_wqe_hdr { uint8_t reserved128[16]; } rq_wqe_hdr_t, *prq_wqe_hdr_t; +/* RQ/SRQ WQE V3 */ +/* rq_wqe_v3 (size:4096b/512B) */ + +typedef struct rq_wqe_v3 { + /* wqe_type is 8 b */ + uint8_t wqe_type; + /* + * RQ/SRQ WQE V3. This WQE is used for posting buffers on + * an RQ or SRQ. + */ + #define RQ_WQE_V3_WQE_TYPE_RCV_V3 UINT32_C(0x90) + #define RQ_WQE_V3_WQE_TYPE_LAST RQ_WQE_V3_WQE_TYPE_RCV_V3 + /* No flags supported for this WQE type. */ + uint8_t flags; + /* + * Specify the total number 16B chunks that make up the valid portion + * of the WQE. This includes the first chunk that is the WQE + * structure and up to 30 SGE structures. The maximum value for this + * field is 32, representing a maximum-sized WQE of 512B. + */ + uint8_t wqe_size; + uint8_t reserved1; + /* This value will be returned in the completion. */ + uint32_t opaque; + uint64_t reserved2; + /* + * The data field for RQ WQE is filled with from 1 to 30 SGE + * structures as defined by the wqe_size field. + */ + uint32_t data[124]; +} rq_wqe_v3_t, *prq_wqe_v3_t; + +/* RQ/SRQ WQE V3 header. */ +/* rq_wqe_hdr_v3 (size:128b/16B) */ + +typedef struct rq_wqe_hdr_v3 { + /* wqe_type is 8 b */ + uint8_t wqe_type; + /* + * RQ/SRQ WQE V3. This WQE is used for posting buffers on + * an RQ or SRQ. + */ + #define RQ_WQE_HDR_V3_WQE_TYPE_RCV_V3 UINT32_C(0x90) + #define RQ_WQE_HDR_V3_WQE_TYPE_LAST RQ_WQE_HDR_V3_WQE_TYPE_RCV_V3 + /* No flags supported for this WQE type. */ + uint8_t flags; + /* + * Specify the total number 16B chunks that make up the valid portion + * of the WQE. This includes the first chunk that is the WQE + * structure and up to 30 SGE structures. The maximum value for this + * field is 32, representing a maximum-sized WQE of 512B. + */ + uint8_t wqe_size; + uint8_t reserved1; + /* This value will be returned in the completion. */ + uint32_t opaque; + uint64_t reserved2; +} rq_wqe_hdr_v3_t, *prq_wqe_hdr_v3_t; + /* cq_base (size:256b/32B) */ typedef struct cq_base { @@ -72719,14 +84651,14 @@ typedef struct cq_base { uint64_t reserved64_3; uint8_t cqe_type_toggle; /* - * Indicate valid completion - written by the chip. Cumulus + * Indicate valid completion - written by the chip. The NIC * toggle this bit each time it finished consuming all PBL - * entries + * entries. */ - #define CQ_BASE_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ - #define CQ_BASE_CQE_TYPE_MASK UINT32_C(0x1e) - #define CQ_BASE_CQE_TYPE_SFT 1 + #define CQ_BASE_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_BASE_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_BASE_CQE_TYPE_SFT 1 /* * Requester completion - This is used for both RC and UD SQ * completions. @@ -72736,17 +84668,17 @@ typedef struct cq_base { * Responder RC Completion - This is used for both RQ and SRQ * completions for RC service QPs. */ - #define CQ_BASE_CQE_TYPE_RES_RC (UINT32_C(0x1) << 1) + #define CQ_BASE_CQE_TYPE_RES_RC (UINT32_C(0x1) << 1) /* * Responder UD Completion - This is used for both RQ and SRQ * completion for UD service QPs. */ - #define CQ_BASE_CQE_TYPE_RES_UD (UINT32_C(0x2) << 1) + #define CQ_BASE_CQE_TYPE_RES_UD (UINT32_C(0x2) << 1) /* * Responder RawEth and QP1 Completion - This is used for RQ * completion for RawEth service and QP1 service QPs. */ - #define CQ_BASE_CQE_TYPE_RES_RAWETH_QP1 (UINT32_C(0x3) << 1) + #define CQ_BASE_CQE_TYPE_RES_RAWETH_QP1 (UINT32_C(0x3) << 1) /* * Responder UD completion with CFA. This is used for both RQ * and SQ completion for UD service QPs. It includes cfa fields @@ -72754,22 +84686,188 @@ typedef struct cq_base { */ #define CQ_BASE_CQE_TYPE_RES_UD_CFA (UINT32_C(0x4) << 1) /* + * Requester completion V3 - This is used for both RC and UD SQ + * completions. + */ + #define CQ_BASE_CQE_TYPE_REQ_V3 (UINT32_C(0x8) << 1) + /* + * Responder RC Completion V3 - This is used for both RQ and SRQ + * completions for RC service QPs. + */ + #define CQ_BASE_CQE_TYPE_RES_RC_V3 (UINT32_C(0x9) << 1) + /* + * Responder UD Completion V3 - This is used for both RQ and SRQ + * completion for UD service QPs. It is also used for QP1 QPs + * that are treated as UD. + */ + #define CQ_BASE_CQE_TYPE_RES_UD_V3 (UINT32_C(0xa) << 1) + /* + * Responder RawEth and QP1 Completion V3 - This is used for RQ and + * SRQ completion for RawEth service. It is also used for QP1 QPs + * that are treated as RawEth. + */ + #define CQ_BASE_CQE_TYPE_RES_RAWETH_QP1_V3 (UINT32_C(0xb) << 1) + /* + * Responder UD Completion with CFA V3 - This is used for both RQ + * and SRQ completion for UD service QPs. It includes CFA fields + * (some of which carry VLAN information), in place of the QP + * handle. It is also used for QP1 QPs that are treated as UD. + */ + #define CQ_BASE_CQE_TYPE_RES_UD_CFA_V3 (UINT32_C(0xc) << 1) + /* * NO_OP completion - This is used to indicate that no - * operation completion. + * operation completed. */ - #define CQ_BASE_CQE_TYPE_NO_OP (UINT32_C(0xd) << 1) + #define CQ_BASE_CQE_TYPE_NO_OP (UINT32_C(0xd) << 1) /* * Terminal completion - This is used to indicate that no * further completions will be made for this QP on this CQ. */ #define CQ_BASE_CQE_TYPE_TERMINAL (UINT32_C(0xe) << 1) - /* Cut off CQE; for CQ resize see CQ and SRQ Resize */ - #define CQ_BASE_CQE_TYPE_CUT_OFF (UINT32_C(0xf) << 1) - #define CQ_BASE_CQE_TYPE_LAST CQ_BASE_CQE_TYPE_CUT_OFF + /* + * Cut off CQE; for CQ resize. This CQE is written to the "old" + * CQ as the last CQE written. SW may use this to know when the + * "old" CQ can be destroyed. + */ + #define CQ_BASE_CQE_TYPE_CUT_OFF (UINT32_C(0xf) << 1) + #define CQ_BASE_CQE_TYPE_LAST CQ_BASE_CQE_TYPE_CUT_OFF /* This field indicates the status for the CQE. */ uint8_t status; + /* The operation completed successfully. */ + #define CQ_BASE_STATUS_OK UINT32_C(0x0) + /* + * An unexpected BTH opcode or a First/Middle packet that is not + * the full MTU size was returned by the responder. + * + * This is a fatal error detected by the requester Rx. + */ + #define CQ_BASE_STATUS_BAD_RESPONSE_ERR UINT32_C(0x1) + /* + * Generated for a WQE posted to the local SQ when the sum of the + * lengths of the SGEs in the WQE exceeds the maximum message + * length of 2^31 bytes. + * + * Generated for a WQE posted to the local RQ/SRQ when the sum of + * the lengths of the SGEs in the WQE is too small to receive the + * (valid) incoming message or the length of the incoming message + * is greater than the maximum message size supported. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_BASE_STATUS_LOCAL_LENGTH_ERR UINT32_C(0x2) + /* + * This indicates that the packet was too long for the WQE provided + * on the SRQ/RQ. + * + * This is not a fatal error. All the fields in the CQE are valid. + */ + #define CQ_BASE_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x3) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_BASE_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_BASE_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * A protection error occurred on a local data buffer during the + * processing of a RDMA Write with Immediate Data operation sent + * from the remote node. + * + * This is a fatal error detected by the responder Rx. Only the + * opaque field in the CQE is valid. + */ + #define CQ_BASE_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x6) + /* + * The SSC detected an error on a local memory operation from the + * SQ (fast-register, local invalidate, or bind). + * + * This is a fatal error detected by the requester Tx. + */ + #define CQ_BASE_STATUS_MEMORY_MGT_OPERATION_ERR UINT32_C(0x7) + /* + * An invalid message was received by the responder. This could be + * an operation that is not supported by this QP, an IRRQ overflow + * error, or the length in an RDMA operation is greater than the + * maximum message size (2^31 bytes). + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Invalid Request. For responder + * CQEs, only the opaque field is valid. + */ + #define CQ_BASE_STATUS_REMOTE_INVALID_REQUEST_ERR UINT32_C(0x8) + /* + * A protection error occurred on a remote data buffer to be read + * by an RDMA Read, written by an RDMA Write or accessed by an + * atomic operation. This error is reported only on RDMA operations + * or atomic operations. + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Remote Access Violation. + */ + #define CQ_BASE_STATUS_REMOTE_ACCESS_ERR UINT32_C(0x9) + /* + * The operation could not be completed successfully by the + * responder. Possible causes include an RQ/SRQ WQE format error, + * an SSC error when validating an SGE from an RQ/SRQ WQE, or the + * message received was too long for the RQ/SRQ WQE. + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Remote Operation Error. + */ + #define CQ_BASE_STATUS_REMOTE_OPERATION_ERR UINT32_C(0xa) + /* + * The RNR NAK retry count was exceeded while trying to send this + * message. + * + * This is a fatal error detected by the requester. + */ + #define CQ_BASE_STATUS_RNR_NAK_RETRY_CNT_ERR UINT32_C(0xb) + /* + * The local transport timeout retry counter was exceeded while + * trying to send this message. + * + * This is a fatal error detected by the requester. + */ + #define CQ_BASE_STATUS_TRANSPORT_RETRY_CNT_ERR UINT32_C(0xc) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_BASE_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE had already been taken off the RQ/SRQ when a fatal error + * was detected on responder Rx. Only the opaque field in the CQE + * is valid. + */ + #define CQ_BASE_STATUS_HW_FLUSH_ERR UINT32_C(0xe) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_BASE_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_BASE_STATUS_LAST CQ_BASE_STATUS_OVERFLOW_ERR uint16_t reserved16; - uint32_t reserved32; + /* + * This value is from the WQE that is being completed. This field is + * only applicable to V3 version of CQEs. + */ + uint32_t opaque; } cq_base_t, *pcq_base_t; /* Requester CQ CQE */ @@ -72783,7 +84881,7 @@ typedef struct cq_req { uint64_t qp_handle; /* * SQ Consumer Index - points to the entry just past the last WQE - * that has been completed by the chip. Wraps around at + * that has been completed by the chip. Wraps around at * QPC.sq_size (i.e. the valid range of the SQ Consumer Index is 0 * to (QPC.sq_size - 1)). */ @@ -72798,7 +84896,7 @@ typedef struct cq_req { * entries */ #define CQ_REQ_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_REQ_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_REQ_CQE_TYPE_SFT 1 /* @@ -72883,7 +84981,7 @@ typedef struct cq_res_rc { * entries */ #define CQ_RES_RC_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_RC_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_RC_CQE_TYPE_SFT 1 /* @@ -72989,7 +85087,7 @@ typedef struct cq_res_ud { * entries */ #define CQ_RES_UD_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_UD_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_UD_CQE_TYPE_SFT 1 /* @@ -73009,7 +85107,7 @@ typedef struct cq_res_ud { * This indicates that write access was not allowed for * at least one of the SGEs in the WQE. * - * This is a fatal error. Only the srq_or_rq_wr_id is field + * This is a fatal error. Only the srq_or_rq_wr_id is field * is valid. */ #define CQ_RES_UD_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x1) @@ -73017,7 +85115,7 @@ typedef struct cq_res_ud { * This indicates that the packet was too long for the WQE * provided on the SRQ/RQ. * - * This is not a fatal error. All the fields are valid. + * This is not a fatal error. All the fields are valid. */ #define CQ_RES_UD_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x2) /* LOCAL_PROTECTION_ERR is 3 */ @@ -73061,7 +85159,7 @@ typedef struct cq_res_ud { */ #define CQ_RES_UD_FLAGS_META_FORMAT_MASK UINT32_C(0x3c0) #define CQ_RES_UD_FLAGS_META_FORMAT_SFT 6 - /* No metadata information. Value is zero. */ + /* No metadata information. Value is zero. */ #define CQ_RES_UD_FLAGS_META_FORMAT_NONE (UINT32_C(0x0) << 6) /* * The metadata field contains the VLAN tag and TPID value. @@ -73159,7 +85257,7 @@ typedef struct cq_res_ud_v2 { * entries */ #define CQ_RES_UD_V2_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_UD_V2_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_UD_V2_CQE_TYPE_SFT 1 /* @@ -73179,7 +85277,7 @@ typedef struct cq_res_ud_v2 { * This indicates that write access was not allowed for * at least one of the SGEs in the WQE. * - * This is a fatal error. Only the srq_or_rq_wr_id is field + * This is a fatal error. Only the srq_or_rq_wr_id is field * is valid. */ #define CQ_RES_UD_V2_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x1) @@ -73187,7 +85285,7 @@ typedef struct cq_res_ud_v2 { * This indicates that the packet was too long for the WQE * provided on the SRQ/RQ. * - * This is not a fatal error. All the fields are valid. + * This is not a fatal error. All the fields are valid. */ #define CQ_RES_UD_V2_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x2) /* LOCAL_PROTECTION_ERR is 3 */ @@ -73228,7 +85326,7 @@ typedef struct cq_res_ud_v2 { /* The field indicates what format the metadata field is. */ #define CQ_RES_UD_V2_FLAGS_META_FORMAT_MASK UINT32_C(0x3c0) #define CQ_RES_UD_V2_FLAGS_META_FORMAT_SFT 6 - /* No metadata information. Value is zero. */ + /* No metadata information. Value is zero. */ #define CQ_RES_UD_V2_FLAGS_META_FORMAT_NONE (UINT32_C(0x0) << 6) /* * The {metadata1, metadata0} fields contain the vtag @@ -73326,7 +85424,7 @@ typedef struct cq_res_ud_cfa { uint32_t qid; /* * This value indicates the QPID associated with this operation. - * The driver will use the qid from thie CQE to map a QP handle + * The driver will use the qid from this CQE to map a QP handle * in the completion record returned to the application. */ #define CQ_RES_UD_CFA_QID_MASK UINT32_C(0xfffff) @@ -73361,7 +85459,7 @@ typedef struct cq_res_ud_cfa { * entries */ #define CQ_RES_UD_CFA_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_UD_CFA_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_UD_CFA_CQE_TYPE_SFT 1 /* @@ -73524,7 +85622,7 @@ typedef struct cq_res_ud_cfa_v2 { uint32_t qid; /* * This value indicates the QPID associated with this operation. - * The driver will use the qid from thie CQE to map a QP handle + * The driver will use the qid from this CQE to map a QP handle * in the completion record returned to the application. */ #define CQ_RES_UD_CFA_V2_QID_MASK UINT32_C(0xfffff) @@ -73556,7 +85654,7 @@ typedef struct cq_res_ud_cfa_v2 { * entries */ #define CQ_RES_UD_CFA_V2_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_UD_CFA_V2_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_UD_CFA_V2_CQE_TYPE_SFT 1 /* @@ -73627,7 +85725,7 @@ typedef struct cq_res_ud_cfa_v2 { /* The field indicates what format the metadata field is. */ #define CQ_RES_UD_CFA_V2_FLAGS_META_FORMAT_MASK UINT32_C(0x3c0) #define CQ_RES_UD_CFA_V2_FLAGS_META_FORMAT_SFT 6 - /* No metadata information. Value is zero. */ + /* No metadata information. Value is zero. */ #define CQ_RES_UD_CFA_V2_FLAGS_META_FORMAT_NONE (UINT32_C(0x0) << 6) /* * The {metadata1, metadata0} fields contain the vtag @@ -73720,7 +85818,7 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_SFT 0 /* * When this bit is '1', it indicates a packet that has an - * error of some type. Type of error is indicated in + * error of some type. Type of error is indicated in * raweth_qp1_errors. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ERROR UINT32_C(0x1) @@ -73744,31 +85842,36 @@ typedef struct cq_res_raweth_qp1 { /* * TCP Packet: * Indicates that the packet was IP and TCP. - * This indicates that the raweth_qp1_payload_offset field is valid. + * This indicates that the raweth_qp1_payload_offset field is + * valid. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_TCP (UINT32_C(0x2) << 6) /* * UDP Packet: * Indicates that the packet was IP and UDP. - * This indicates that the raweth_qp1_payload_offset field is valid. + * This indicates that the raweth_qp1_payload_offset field is + * valid. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_UDP (UINT32_C(0x3) << 6) /* * FCoE Packet: * Indicates that the packet was recognized as a FCoE. - * This also indicates that the raweth_qp1_payload_offset field is valid. + * This also indicates that the raweth_qp1_payload_offset field + * is valid. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_FCOE (UINT32_C(0x4) << 6) /* * RoCE Packet: * Indicates that the packet was recognized as a RoCE. - * This also indicates that the raweth_qp1_payload_offset field is valid. + * This also indicates that the raweth_qp1_payload_offset field + * is valid. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE (UINT32_C(0x5) << 6) /* * ICMP Packet: * Indicates that the packet was recognized as ICMP. - * This indicates that the raweth_qp1_payload_offset field is valid. + * This indicates that the raweth_qp1_payload_offset field is + * valid. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ICMP (UINT32_C(0x7) << 6) /* @@ -73807,7 +85910,7 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_RAWETH_QP1_ERRORS_T_L4_CS_ERROR UINT32_C(0x80) /* * This indicates that there was a CRC error on either an FCoE - * or RoCE packet. The itype indicates the packet type. + * or RoCE packet. The itype indicates the packet type. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_ERRORS_CRC_ERROR UINT32_C(0x100) /* @@ -73939,23 +86042,27 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_L4_CS_CALC UINT32_C(0x2) /* * This indicates that the ip checksum was calculated for the - * tunnel header and that the t_ip_cs_error field indicates if there - * was an error. + * tunnel header and that the t_ip_cs_error field indicates if + * there was an error. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_T_IP_CS_CALC UINT32_C(0x4) /* * This indicates that the UDP checksum was - * calculated for the tunnel packet and that the t_l4_cs_error field - * indicates if there was an error. + * calculated for the tunnel packet and that the t_l4_cs_error + * field indicates if there was an error. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_T_L4_CS_CALC UINT32_C(0x8) - /* This value indicates what format the raweth_qp1_metadata field is. */ + /* + * This value indicates what format the raweth_qp1_metadata field + * is. + */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0) #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_SFT 4 - /* No metadata information. Value is zero. */ + /* No metadata information. Value is zero. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4) /* - * The raweth_qp1_metadata field contains the VLAN tag and TPID value. + * The raweth_qp1_metadata field contains the VLAN tag and TPID + * value. * - raweth_qp1_metadata[11:0] contains the vlan VID value. * - raweth_qp1_metadata[12] contains the vlan DE value. * - raweth_qp1_metadata[15:13] contains the vlan PRI value. @@ -73992,7 +86099,7 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_LAST CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_HDR_OFFSET /* * This field indicates the IP type for the inner-most IP header. - * A value of '0' indicates IPv4. A value of '1' indicates IPv6. + * A value of '0' indicates IPv4. A value of '1' indicates IPv6. * This value is only valid if itype indicates a packet * with an IP header. */ @@ -74009,9 +86116,9 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_EXT_META_FORMAT_MASK UINT32_C(0xc00) #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_EXT_META_FORMAT_SFT 10 /* - * This value is the complete 1's complement checksum calculated from - * the start of the outer L3 header to the end of the packet (not - * including the ethernet crc). It is valid when the + * This value is the complete 1's complement checksum calculated + * from the start of the outer L3 header to the end of the packet + * (not including the ethernet crc). It is valid when the * 'complete_checksum_calc' flag is set. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_COMPLETE_CHECKSUM_MASK UINT32_C(0xffff0000) @@ -74041,7 +86148,7 @@ typedef struct cq_res_raweth_qp1 { * entries */ #define CQ_RES_RAWETH_QP1_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_RAWETH_QP1_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_RAWETH_QP1_CQE_TYPE_SFT 1 /* @@ -74061,7 +86168,7 @@ typedef struct cq_res_raweth_qp1 { * This indicates that write access was not allowed for * at least one of the SGEs in the WQE. * - * This is a fatal error. Only the srq_or_rq_wr_id is field + * This is a fatal error. Only the srq_or_rq_wr_id is field * is valid. */ #define CQ_RES_RAWETH_QP1_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x1) @@ -74069,7 +86176,7 @@ typedef struct cq_res_raweth_qp1 { * This indicates that the packet was too long for the WQE * provided on the RQ. * - * This is not a fatal error. All the fields are valid. + * This is not a fatal error. All the fields are valid. */ #define CQ_RES_RAWETH_QP1_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x2) /* LOCAL_PROTECTION_ERR is 3 */ @@ -74103,10 +86210,9 @@ typedef struct cq_res_raweth_qp1 { #define CQ_RES_RAWETH_QP1_SRQ_OR_RQ_WR_ID_MASK UINT32_C(0xfffff) #define CQ_RES_RAWETH_QP1_SRQ_OR_RQ_WR_ID_SFT 0 /* - * This value indicates the offset in bytes from the beginning of the packet - * where the inner payload starts. This value is valid for TCP, UDP, - * FCoE, and RoCE packets. - * + * This value indicates the offset in bytes from the beginning of the + * packet where the inner payload starts. This value is valid for + * TCP, UDP, FCoE, and RoCE packets. * A value of zero indicates an offset of 256 bytes. */ #define CQ_RES_RAWETH_QP1_RAWETH_QP1_PAYLOAD_OFFSET_MASK UINT32_C(0xff000000) @@ -74129,7 +86235,7 @@ typedef struct cq_res_raweth_qp1_v2 { #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_FLAGS_SFT 0 /* * When this bit is '1', it indicates a packet that has an - * error of some type. Type of error is indicated in + * error of some type. Type of error is indicated in * raweth_qp1_errors. */ #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_FLAGS_ERROR UINT32_C(0x1) @@ -74221,7 +86327,7 @@ typedef struct cq_res_raweth_qp1_v2 { #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_ERRORS_T_L4_CS_ERROR UINT32_C(0x80) /* * This indicates that there was a CRC error on either an FCoE - * or RoCE packet. The itype indicates the packet type. + * or RoCE packet. The itype indicates the packet type. */ #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_ERRORS_CRC_ERROR UINT32_C(0x100) /* @@ -74415,7 +86521,7 @@ typedef struct cq_res_raweth_qp1_v2 { #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_FLAGS2_META_FORMAT_LAST CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_FLAGS2_META_FORMAT_HDR_OFFSET /* * This field indicates the IP type for the inner-most IP header. - * A value of '0' indicates IPv4. A value of '1' indicates IPv6. + * A value of '0' indicates IPv4. A value of '1' indicates IPv6. * This value is only valid if itype indicates a packet * with an IP header. */ @@ -74460,7 +86566,7 @@ typedef struct cq_res_raweth_qp1_v2 { * entries */ #define CQ_RES_RAWETH_QP1_V2_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_RES_RAWETH_QP1_V2_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_RES_RAWETH_QP1_V2_CQE_TYPE_SFT 1 /* @@ -74480,7 +86586,7 @@ typedef struct cq_res_raweth_qp1_v2 { * This indicates that write access was not allowed for * at least one of the SGEs in the WQE. * - * This is a fatal error. Only the srq_or_rq_wr_id is field + * This is a fatal error. Only the srq_or_rq_wr_id is field * is valid. */ #define CQ_RES_RAWETH_QP1_V2_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x1) @@ -74488,7 +86594,7 @@ typedef struct cq_res_raweth_qp1_v2 { * This indicates that the packet was too long for the WQE * provided on the RQ. * - * This is not a fatal error. All the fields are valid. + * This is not a fatal error. All the fields are valid. */ #define CQ_RES_RAWETH_QP1_V2_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x2) /* LOCAL_PROTECTION_ERR is 3 */ @@ -74543,7 +86649,7 @@ typedef struct cq_res_raweth_qp1_v2 { #define CQ_RES_RAWETH_QP1_V2_CFA_METADATA1_VALID UINT32_C(0x800000) /* * This value indicates the offset in bytes from the beginning of - * the packet where the inner payload starts. This value is valid + * the packet where the inner payload starts. This value is valid * for TCP, UDP, FCoE, and RoCE packets. * * A value of zero indicates an offset of 256 bytes. @@ -74552,7 +86658,10 @@ typedef struct cq_res_raweth_qp1_v2 { #define CQ_RES_RAWETH_QP1_V2_RAWETH_QP1_PAYLOAD_OFFSET_SFT 24 } cq_res_raweth_qp1_v2_t, *pcq_res_raweth_qp1_v2_t; -/* Terminal CQE */ +/* + * This is the terminal CQE structure. This CQE is generated to + * indicate that no further completions will be generated for this QP. + */ /* cq_terminal (size:256b/32B) */ typedef struct cq_terminal { @@ -74562,12 +86671,12 @@ typedef struct cq_terminal { */ uint64_t qp_handle; /* - * Final SQ Consumer Index value. Any additional SQ WQEs will + * Final SQ Consumer Index value. Any additional SQ WQEs will * have to be completed by the user provider. */ uint16_t sq_cons_idx; /* - * Final RQ Consumer Index value. Any additional RQ WQEs will + * Final RQ Consumer Index value. Any additional RQ WQEs will * have to be completed by the user provider. */ uint16_t rq_cons_idx; @@ -74580,7 +86689,7 @@ typedef struct cq_terminal { * entries */ #define CQ_TERMINAL_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_TERMINAL_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_TERMINAL_CQE_TYPE_SFT 1 /* @@ -74591,7 +86700,7 @@ typedef struct cq_terminal { #define CQ_TERMINAL_CQE_TYPE_LAST CQ_TERMINAL_CQE_TYPE_TERMINAL /* This field indicates the status for the CQE. */ uint8_t status; - /* OK is 0 */ + /* The operation completed successfully. */ #define CQ_TERMINAL_STATUS_OK UINT32_C(0x0) #define CQ_TERMINAL_STATUS_LAST CQ_TERMINAL_STATUS_OK uint16_t reserved16; @@ -74607,12 +86716,12 @@ typedef struct cq_cutoff { uint64_t reserved64_3; uint8_t cqe_type_toggle; /* - * Indicate valid completion - written by the chip. Cumulus - * toggle this bit each time it finished consuming all PBL + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL * entries */ #define CQ_CUTOFF_TOGGLE UINT32_C(0x1) - /* This field defines the type of SQ WQE. */ + /* This field defines the type of CQE. */ #define CQ_CUTOFF_CQE_TYPE_MASK UINT32_C(0x1e) #define CQ_CUTOFF_CQE_TYPE_SFT 1 /* Cut off CQE; for CQ resize see CQ and SRQ Resize */ @@ -74623,7 +86732,9 @@ typedef struct cq_cutoff { * acknowledge this CQ resize operation. When this CQE is * processed, the driver should send a CQ_CUTOFF_ACK doorbell * to the chip to let the chip know that the resize operation - * is complete. This value is used by HW to detect old and + * is complete. + * + * This value is used by HW to detect old and * stale CQ_CUTOFF_ACK doorbells that are caused by having * a backup doorbell location or by PCI or other reordering * problems. Only doorbells with the latest value will be honored. @@ -74634,13 +86745,1227 @@ typedef struct cq_cutoff { #define CQ_CUTOFF_RESIZE_TOGGLE_SFT 5 /* This field indicates the status for the CQE. */ uint8_t status; - /* OK is 0 */ + /* The operation completed successfully. */ #define CQ_CUTOFF_STATUS_OK UINT32_C(0x0) #define CQ_CUTOFF_STATUS_LAST CQ_CUTOFF_STATUS_OK uint16_t reserved16; uint32_t reserved32; } cq_cutoff_t, *pcq_cutoff_t; +/* No-Op CQE */ +/* cq_no_op (size:256b/32B) */ + +typedef struct cq_no_op { + uint64_t reserved64_1; + uint64_t reserved64_2; + uint64_t reserved64_3; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries. + */ + #define CQ_NO_OP_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_NO_OP_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_NO_OP_CQE_TYPE_SFT 1 + /* + * NO-OP completion - This is used to indicate that no operation + * completed. + */ + #define CQ_NO_OP_CQE_TYPE_NO_OP (UINT32_C(0xd) << 1) + #define CQ_NO_OP_CQE_TYPE_LAST CQ_NO_OP_CQE_TYPE_NO_OP + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_NO_OP_STATUS_OK UINT32_C(0x0) + #define CQ_NO_OP_STATUS_LAST CQ_NO_OP_STATUS_OK + uint16_t reserved16; + uint32_t reserved32; +} cq_no_op_t, *pcq_no_op_t; + +/* + * This is the Requester CQE V3 structure. This is used to complete each + * signaled SQ WQE. The sq_cons_idx and opaque is used to indicate + * which WQE has been completed. When a WQE is completed, it indicates + * that all WQEs before it in the SQ are also completed without error. + * Space freed by completed WQEs can be used for new WQEs. + */ +/* cq_req_v3 (size:256b/32B) */ + +typedef struct cq_req_v3 { + /* + * This is an application level ID used to identify the + * QP and its SQ and RQ. + */ + uint64_t qp_handle; + /* + * SQ Consumer Index - points to the entry just past the last WQE + * that has been completed by the chip. Wraps around at QPC.sq_size + * (i.e. the valid range of the SQ Consumer Index is 0 to + * (QPC.sq_size - 1)). The sq_cons_idx is in 16B units (as is + * QPC.sq_size). + * + * User can determine available space in the SQ by comparing + * sq_cons_idx to a sq_prod_idx maintained by the user. When the two + * values are equal, the SQ is empty. When + * (sq_prod_idx+1)%QPC.sq_size==sq_cons_idx, the queue is full. + */ + uint16_t sq_cons_idx; + uint16_t reserved1; + uint32_t reserved2; + uint64_t reserved3; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries. + */ + #define CQ_REQ_V3_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_REQ_V3_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_REQ_V3_CQE_TYPE_SFT 1 + /* + * Requester completion V3 - This is used for both RC and UD SQ + * completions. + */ + #define CQ_REQ_V3_CQE_TYPE_REQ_V3 (UINT32_C(0x8) << 1) + #define CQ_REQ_V3_CQE_TYPE_LAST CQ_REQ_V3_CQE_TYPE_REQ_V3 + /* + * When this bit is '1', it indicates that the packet completed + * was transmitted using the push accelerated data provided by + * the driver. When this bit is '0', it indicates that the packet + * had not push acceleration data written or was executed as a + * normal packet even though push data was provided. + * + * Note: This field is intended to be used for driver-generated push + * statistics. As such, It is not applicable for RC since not all + * RC packets return a CQE. + */ + #define CQ_REQ_V3_PUSH UINT32_C(0x20) + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_REQ_V3_STATUS_OK UINT32_C(0x0) + /* + * An unexpected BTH opcode or a First/Middle packet that is not + * the full MTU size was returned by the responder. + * + * This is a fatal error detected by the requester Rx. + */ + #define CQ_REQ_V3_STATUS_BAD_RESPONSE_ERR UINT32_C(0x1) + /* + * Generated for a WQE posted to the local SQ when the sum of the + * lengths of the SGEs in the WQE exceeds the maximum message + * length of 2^31 bytes. + * + * Generated for a WQE posted to the local RQ/SRQ when the sum of + * the lengths of the SGEs in the WQE is too small to receive the + * (valid) incoming message or the length of the incoming message + * is greater than the maximum message size supported. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_REQ_V3_STATUS_LOCAL_LENGTH_ERR UINT32_C(0x2) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_REQ_V3_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_REQ_V3_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * The SSC detected an error on a local memory operation from the + * SQ (fast-register, local invalidate, or bind). + * + * This is a fatal error detected by the requester Tx. + */ + #define CQ_REQ_V3_STATUS_MEMORY_MGT_OPERATION_ERR UINT32_C(0x7) + /* + * An invalid message was received by the responder. This could be + * an operation that is not supported by this QP, an IRRQ overflow + * error, or the length in an RDMA operation is greater than the + * maximum message size (2^31 bytes). + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Invalid Request. For responder + * CQEs, only the opaque field is valid. + */ + #define CQ_REQ_V3_STATUS_REMOTE_INVALID_REQUEST_ERR UINT32_C(0x8) + /* + * A protection error occurred on a remote data buffer to be read + * by an RDMA Read, written by an RDMA Write or accessed by an + * atomic operation. This error is reported only on RDMA operations + * or atomic operations. + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Remote Access Violation. + */ + #define CQ_REQ_V3_STATUS_REMOTE_ACCESS_ERR UINT32_C(0x9) + /* + * The operation could not be completed successfully by the + * responder. Possible causes include an RQ/SRQ WQE format error, + * an SSC error when validating an SGE from an RQ/SRQ WQE, or the + * message received was too long for the RQ/SRQ WQE. + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Remote Operation Error. + */ + #define CQ_REQ_V3_STATUS_REMOTE_OPERATION_ERR UINT32_C(0xa) + /* + * The RNR NAK retry count was exceeded while trying to send this + * message. + * + * This is a fatal error detected by the requester. + */ + #define CQ_REQ_V3_STATUS_RNR_NAK_RETRY_CNT_ERR UINT32_C(0xb) + /* + * The local transport timeout retry counter was exceeded while + * trying to send this message. + * + * This is a fatal error detected by the requester. + */ + #define CQ_REQ_V3_STATUS_TRANSPORT_RETRY_CNT_ERR UINT32_C(0xc) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_REQ_V3_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_REQ_V3_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_REQ_V3_STATUS_LAST CQ_REQ_V3_STATUS_OVERFLOW_ERR + uint16_t reserved4; + /* This value is from the WQE that is being completed. */ + uint32_t opaque; +} cq_req_v3_t, *pcq_req_v3_t; + +/* + * This is the Responder RQ/SRQ CQE V3 structure for RC QPs. This is + * used to complete each RQ/SRQ WQE. When the WQE is completed, it + * indicates that there is room for one more WQE on the corresponding + * RQ/SRQ. + * + * User can determine available space in the RQ/SRQ by comparing + * a rq_cons_idx to a rq_prod_idx, both maintained by the user. The + * range for rq_prod/cons_idx is from 0 to QPC.rq_size-1. The + * rq_prod_idx value increments by one for each WQE that is added to + * the RQ/SRQ by the user. Value must be wrapped at rq_size. The + * rq_cons_idx value increments by one for each WQE that is completed + * from that particular RQ/SRQ. The qp_handle can be used by the user + * to determine what RQ/SRQ to increment. Value must also be wrapped at + * rq_size. When the two values are equal, the RQ/SRQ is empty. When + * (rq_prod_idx+1)%QPC.rq_size==rq_cons_idx, the queue is full. + */ +/* cq_res_rc_v3 (size:256b/32B) */ + +typedef struct cq_res_rc_v3 { + /* + * The length of the message's payload in bytes, stored in + * the SGEs + */ + uint32_t length; + /* + * Immediate data in case the imm_flag set, R_Key to be + * invalidated in case inv_flag is set. + */ + uint32_t imm_data_or_inv_r_key; + /* + * This is an application level ID used to identify the + * QP and its SQ and RQ. + */ + uint64_t qp_handle; + /* + * Opaque value - valid when inv_flag is set. Used by driver + * to reference the buffer used to store PBL when the MR was + * fast registered. The driver can reclaim this buffer after + * an MR was remotely invalidated. The controller take that + * value from the MR referenced by R_Key + */ + uint64_t mr_handle; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries. + */ + #define CQ_RES_RC_V3_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_RES_RC_V3_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_RES_RC_V3_CQE_TYPE_SFT 1 + /* + * Responder RC Completion - This is used for both RQ and SRQ + * completions for RC service QPs. + */ + #define CQ_RES_RC_V3_CQE_TYPE_RES_RC_V3 (UINT32_C(0x9) << 1) + #define CQ_RES_RC_V3_CQE_TYPE_LAST CQ_RES_RC_V3_CQE_TYPE_RES_RC_V3 + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_RES_RC_V3_STATUS_OK UINT32_C(0x0) + /* + * Generated for a WQE posted to the local SQ when the sum of the + * lengths of the SGEs in the WQE exceeds the maximum message + * length of 2^31 bytes. + * + * Generated for a WQE posted to the local RQ/SRQ when the sum of + * the lengths of the SGEs in the WQE is too small to receive the + * (valid) incoming message or the length of the incoming message + * is greater than the maximum message size supported. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_RC_V3_STATUS_LOCAL_LENGTH_ERR UINT32_C(0x2) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_RC_V3_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_RC_V3_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * A protection error occurred on a local data buffer during the + * processing of a RDMA Write with Immediate Data operation sent + * from the remote node. + * + * This is a fatal error detected by the responder Rx. Only the + * opaque field in the CQE is valid. + */ + #define CQ_RES_RC_V3_STATUS_LOCAL_ACCESS_ERROR UINT32_C(0x6) + /* + * An invalid message was received by the responder. This could be + * an operation that is not supported by this QP, an IRRQ overflow + * error, or the length in an RDMA operation is greater than the + * maximum message size (2^31 bytes). + * + * This is a fatal error detected by the responder and communicated + * back to the requester using a NAK-Invalid Request. For responder + * CQEs, only the opaque field is valid. + */ + #define CQ_RES_RC_V3_STATUS_REMOTE_INVALID_REQUEST_ERR UINT32_C(0x8) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_RES_RC_V3_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE had already been taken off the RQ/SRQ when a fatal error + * was detected on responder Rx. Only the opaque field in the CQE + * is valid. + */ + #define CQ_RES_RC_V3_STATUS_HW_FLUSH_ERR UINT32_C(0xe) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_RES_RC_V3_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_RES_RC_V3_STATUS_LAST CQ_RES_RC_V3_STATUS_OVERFLOW_ERR + uint16_t flags; + /* + * This flag indicates that the completion is for a SRQ entry + * rather than for an RQ entry. + */ + #define CQ_RES_RC_V3_FLAGS_SRQ UINT32_C(0x1) + /* CQE relates to RQ WQE. */ + #define CQ_RES_RC_V3_FLAGS_SRQ_RQ UINT32_C(0x0) + /* CQE relates to SRQ WQE. */ + #define CQ_RES_RC_V3_FLAGS_SRQ_SRQ UINT32_C(0x1) + #define CQ_RES_RC_V3_FLAGS_SRQ_LAST CQ_RES_RC_V3_FLAGS_SRQ_SRQ + /* Immediate data indicator */ + #define CQ_RES_RC_V3_FLAGS_IMM UINT32_C(0x2) + /* R_Key invalidate indicator */ + #define CQ_RES_RC_V3_FLAGS_INV UINT32_C(0x4) + #define CQ_RES_RC_V3_FLAGS_RDMA UINT32_C(0x8) + /* CQE relates to an incoming Send request */ + #define CQ_RES_RC_V3_FLAGS_RDMA_SEND (UINT32_C(0x0) << 3) + /* CQE relates to incoming RDMA Write request */ + #define CQ_RES_RC_V3_FLAGS_RDMA_RDMA_WRITE (UINT32_C(0x1) << 3) + #define CQ_RES_RC_V3_FLAGS_RDMA_LAST CQ_RES_RC_V3_FLAGS_RDMA_RDMA_WRITE + /* This value is from the WQE that is being completed. */ + uint32_t opaque; +} cq_res_rc_v3_t, *pcq_res_rc_v3_t; + +/* + * This is the Responder RQ/SRQ CQE V3 structure for UD QPs and QP1 QPs + * that are treated as UD. This is used to complete RQ/SRQ WQE's. When + * the WQE is completed, it indicates that there is room for one more + * WQE on the corresponding RQ/SRQ. + * + * User can determine available space in the RQ/SRQ by comparing + * a rq_cons_idx to a rq_prod_idx, both maintained by the user. The + * range for rq_prod/cons_idx is from 0 to QPC.rq_size-1. The + * rq_prod_idx value increments by one for each WQE that is added to + * the RQ/SRQ by the user. Value must be wrapped at rq_size. The + * rq_cons_idx value increments by one for each WQE that is completed + * from that particular RQ/SRQ. The qp_handle can be used by the user + * to determine what RQ/SRQ to increment. Value must also be wrapped at + * rq_size. When the two values are equal, the RQ/SRQ is empty. When + * (rq_prod_idx+1)%QPC.rq_size==rq_cons_idx, the queue is full. + */ +/* cq_res_ud_v3 (size:256b/32B) */ + +typedef struct cq_res_ud_v3 { + uint16_t length; + /* + * The length of the message's payload in bytes, stored in + * the SGEs + */ + #define CQ_RES_UD_V3_LENGTH_MASK UINT32_C(0x3fff) + #define CQ_RES_UD_V3_LENGTH_SFT 0 + uint8_t reserved1; + /* Upper 8b of the Source QP value from the DETH header. */ + uint8_t src_qp_high; + /* Immediate data in case the imm_flag set. */ + uint32_t imm_data; + /* + * This is an application level ID used to identify the + * QP and its SQ and RQ. + */ + uint64_t qp_handle; + /* + * Source MAC address for the UD message placed in the WQE + * that is completed by this CQE. + */ + uint16_t src_mac[3]; + /* Lower 16b of the Source QP value from the DETH header. */ + uint16_t src_qp_low; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries. + */ + #define CQ_RES_UD_V3_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_RES_UD_V3_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_RES_UD_V3_CQE_TYPE_SFT 1 + /* + * Responder UD Completion - This is used for both RQ and SRQ + * completion for UD service QPs. It is also used for QP1 QPs + * that are treated as UD. + */ + #define CQ_RES_UD_V3_CQE_TYPE_RES_UD_V3 (UINT32_C(0xa) << 1) + #define CQ_RES_UD_V3_CQE_TYPE_LAST CQ_RES_UD_V3_CQE_TYPE_RES_UD_V3 + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_RES_UD_V3_STATUS_OK UINT32_C(0x0) + /* + * This indicates that the packet was too long for the WQE provided + * on the SRQ/RQ. + * + * This is not a fatal error. All the fields in the CQE are valid. + */ + #define CQ_RES_UD_V3_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x3) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_UD_V3_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_UD_V3_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_RES_UD_V3_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE had already been taken off the RQ/SRQ when a fatal error + * was detected on responder Rx. Only the opaque field in the CQE + * is valid. + */ + #define CQ_RES_UD_V3_STATUS_HW_FLUSH_ERR UINT32_C(0xe) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_RES_UD_V3_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_RES_UD_V3_STATUS_LAST CQ_RES_UD_V3_STATUS_OVERFLOW_ERR + uint16_t flags; + /* + * This flag indicates that the completion is for a SRQ entry + * rather than for an RQ entry. + */ + #define CQ_RES_UD_V3_FLAGS_SRQ UINT32_C(0x1) + /* CQE relates to RQ WQE. */ + #define CQ_RES_UD_V3_FLAGS_SRQ_RQ UINT32_C(0x0) + /* CQE relates to SRQ WQE. */ + #define CQ_RES_UD_V3_FLAGS_SRQ_SRQ UINT32_C(0x1) + #define CQ_RES_UD_V3_FLAGS_SRQ_LAST CQ_RES_UD_V3_FLAGS_SRQ_SRQ + /* Immediate data indicator */ + #define CQ_RES_UD_V3_FLAGS_IMM UINT32_C(0x2) + #define CQ_RES_UD_V3_FLAGS_UNUSED_MASK UINT32_C(0xc) + #define CQ_RES_UD_V3_FLAGS_UNUSED_SFT 2 + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_MASK UINT32_C(0x30) + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_SFT 4 + /* RoCEv1 Message */ + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_V1 (UINT32_C(0x0) << 4) + /* RoCEv2 IPv4 Message */ + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_V2IPV4 (UINT32_C(0x2) << 4) + /* RoCEv2 IPv6 Message */ + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_V2IPV6 (UINT32_C(0x3) << 4) + #define CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_LAST CQ_RES_UD_V3_FLAGS_ROCE_IP_VER_V2IPV6 + /* This value is from the WQE that is being completed. */ + uint32_t opaque; +} cq_res_ud_v3_t, *pcq_res_ud_v3_t; + +/* + * This is the Responder RQ/SRQ CQE V3 structure for RawEth. This is + * used to complete RQ/SRQ WQE's. When the WQE is completed, it + * indicates that there is room for one more WQE on the corresponding + * RQ/SRQ. + * + * User can determine available space in the RQ/SRQ by comparing + * a rq_cons_idx to a rq_prod_idx, both maintained by the user. The + * range for rq_prod/cons_idx is from 0 to QPC.rq_size-1. The + * rq_prod_idx value increments by one for each WQE that is added to + * the RQ/SRQ by the user. Value must be wrapped at rq_size. The + * rq_cons_idx value increments by one for each WQE that is completed + * from that particular RQ/SRQ. The qp_handle can be used by the user + * to determine what RQ/SRQ to increment. Value must also be wrapped at + * rq_size. When the two values are equal, the RQ/SRQ is empty. When + * (rq_prod_idx+1)%QPC.rq_size==rq_cons_idx, the queue is full. + */ +/* cq_res_raweth_qp1_v3 (size:256b/32B) */ + +typedef struct cq_res_raweth_qp1_v3 { + uint16_t length; + /* + * The length of the message's payload in bytes, stored in + * the SGEs + */ + #define CQ_RES_RAWETH_QP1_V3_LENGTH_MASK UINT32_C(0x3fff) + #define CQ_RES_RAWETH_QP1_V3_LENGTH_SFT 0 + uint16_t raweth_qp1_flags_cfa_metadata1; + /* + * When this bit is '1', it indicates a packet that has an + * error of some type. Type of error is indicated in + * raweth_qp1_errors. + */ + #define CQ_RES_RAWETH_QP1_V3_ERROR UINT32_C(0x1) + /* + * This value indicates what the inner packet determined for the + * packet was. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_MASK UINT32_C(0x3c0) + #define CQ_RES_RAWETH_QP1_V3_ITYPE_SFT 6 + /* + * Not Known: + * Indicates that the packet type was not known. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_NOT_KNOWN (UINT32_C(0x0) << 6) + /* + * IP Packet: + * Indicates that the packet was an IP packet, but further + * classification was not possible. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_IP (UINT32_C(0x1) << 6) + /* + * TCP Packet: + * Indicates that the packet was IP and TCP. + * This indicates that the raweth_qp1_payload_offset field is + * valid. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_TCP (UINT32_C(0x2) << 6) + /* + * UDP Packet: + * Indicates that the packet was IP and UDP. + * This indicates that the raweth_qp1_payload_offset field is + * valid. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_UDP (UINT32_C(0x3) << 6) + /* + * FCoE Packet: + * Indicates that the packet was recognized as a FCoE. + * This also indicates that the raweth_qp1_payload_offset field is + * valid. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_FCOE (UINT32_C(0x4) << 6) + /* + * RoCE Packet: + * Indicates that the packet was recognized as a RoCE. + * This also indicates that the raweth_qp1_payload_offset field is + * valid. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_ROCE (UINT32_C(0x5) << 6) + /* + * ICMP Packet: + * Indicates that the packet was recognized as ICMP. + * This indicates that the raweth_qp1_payload_offset field is + * valid. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_ICMP (UINT32_C(0x7) << 6) + /* + * PtP packet wo/timestamp: + * Indicates that the packet was recognized as a PtP + * packet. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_PTP_WO_TIMESTAMP (UINT32_C(0x8) << 6) + /* + * PtP packet w/timestamp: + * Indicates that the packet was recognized as a PtP + * packet and that a timestamp was taken for the packet. + */ + #define CQ_RES_RAWETH_QP1_V3_ITYPE_PTP_W_TIMESTAMP (UINT32_C(0x9) << 6) + #define CQ_RES_RAWETH_QP1_V3_ITYPE_LAST CQ_RES_RAWETH_QP1_V3_ITYPE_PTP_W_TIMESTAMP + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA1_MASK UINT32_C(0xf000) + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA1_SFT 12 + /* When meta_format != 0, this value is the VLAN TPID_SEL. */ + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA1_TPID_SEL_MASK UINT32_C(0x7000) + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA1_TPID_SEL_SFT 12 + /* When meta_format != 0, this value is the VLAN valid. */ + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA1_VALID UINT32_C(0x8000) + uint16_t raweth_qp1_errors; + /* + * This indicates that there was an error in the IP header + * checksum. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_IP_CS_ERROR UINT32_C(0x10) + /* + * This indicates that there was an error in the TCP, UDP + * or ICMP checksum. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_L4_CS_ERROR UINT32_C(0x20) + /* + * This indicates that there was an error in the tunnel + * IP header checksum. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_IP_CS_ERROR UINT32_C(0x40) + /* + * This indicates that there was an error in the tunnel + * UDP checksum. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_L4_CS_ERROR UINT32_C(0x80) + /* + * This indicates that there was a CRC error on either an FCoE + * or RoCE packet. The itype indicates the packet type. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_CRC_ERROR UINT32_C(0x100) + /* + * This indicates that there was an error in the tunnel + * portion of the packet when this + * field is non-zero. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_MASK UINT32_C(0xe00) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_SFT 9 + /* + * No additional error occurred on the tunnel portion + * of the packet of the packet does not have a tunnel. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 9) + /* + * Indicates that IP header version does not match + * expectation from L2 Ethertype for IPv4 and IPv6 + * in the tunnel header. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (UINT32_C(0x1) << 9) + /* + * Indicates that header length is out of range in the + * tunnel header. Valid for + * IPv4. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (UINT32_C(0x2) << 9) + /* + * Indicates that physical packet is shorter than that claimed + * by the tunnel l3 header length. Valid for IPv4, or IPv6 + * tunnel packet packets. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (UINT32_C(0x3) << 9) + /* + * Indicates that the physical packet is shorter than that + * claimed by the tunnel UDP header length for a tunnel + * UDP packet that is not fragmented. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (UINT32_C(0x4) << 9) + /* + * indicates that the IPv4 TTL or IPv6 hop limit check + * have failed (e.g. TTL = 0) in the tunnel header. Valid + * for IPv4, and IPv6. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (UINT32_C(0x5) << 9) + /* + * Indicates that the physical packet is shorter than that + * claimed by the tunnel header length. Valid for GTPv1-U + * packets. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_TOTAL_ERROR (UINT32_C(0x6) << 9) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_LAST CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_T_PKT_ERROR_T_TOTAL_ERROR + /* + * This indicates that there was an error in the inner + * portion of the packet when this + * field is non-zero. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_MASK UINT32_C(0xf000) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_SFT 12 + /* + * No additional error occurred on the tunnel portion + * of the packet of the packet does not have a tunnel. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 12) + /* + * Indicates that IP header version does not match + * expectation from L2 Ethertype for IPv4 and IPv6 or that + * option other than VFT was parsed on + * FCoE packet. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L3_BAD_VERSION (UINT32_C(0x1) << 12) + /* + * indicates that header length is out of range. Valid for + * IPv4 and RoCE + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (UINT32_C(0x2) << 12) + /* + * indicates that the IPv4 TTL or IPv6 hop limit check + * have failed (e.g. TTL = 0). Valid for IPv4, and IPv6 + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L3_BAD_TTL (UINT32_C(0x3) << 12) + /* + * Indicates that physical packet is shorter than that + * claimed by the l3 header length. Valid for IPv4, + * IPv6 packet or RoCE packets. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (UINT32_C(0x4) << 12) + /* + * Indicates that the physical packet is shorter than that + * claimed by the UDP header length for a UDP packet that is + * not fragmented. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (UINT32_C(0x5) << 12) + /* + * Indicates that TCP header length > IP payload. Valid for + * TCP packets only. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (UINT32_C(0x6) << 12) + /* Indicates that TCP header length < 5. Valid for TCP. */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (UINT32_C(0x7) << 12) + /* + * Indicates that TCP option headers result in a TCP header + * size that does not match data offset in TCP header. Valid + * for TCP. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (UINT32_C(0x8) << 12) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_LAST CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN + /* This is data from the CFA as indicated by the meta_format field. */ + uint16_t cfa_metadata0; + /* When meta_format=1, this value is the VLAN VID. */ + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA0_VID_MASK UINT32_C(0xfff) + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA0_VID_SFT 0 + /* When meta_format=1, this value is the VLAN DE. */ + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA0_DE UINT32_C(0x1000) + /* When meta_format=1, this value is the VLAN PRI. */ + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA0_PRI_MASK UINT32_C(0xe000) + #define CQ_RES_RAWETH_QP1_V3_CFA_METADATA0_PRI_SFT 13 + /* + * This is an application level ID used to identify the + * QP and its SQ and RQ. + */ + uint64_t qp_handle; + uint32_t raweth_qp1_flags2; + /* + * This indicates that the ip checksum was calculated for the + * inner packet and that the ip_cs_error field indicates if there + * was an error. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_IP_CS_CALC UINT32_C(0x1) + /* + * This indicates that the TCP, UDP or ICMP checksum was + * calculated for the inner packet and that the l4_cs_error field + * indicates if there was an error. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_L4_CS_CALC UINT32_C(0x2) + /* + * This indicates that the ip checksum was calculated for the + * tunnel header and that the t_ip_cs_error field indicates if + * there was an error. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_CS_CALC UINT32_C(0x4) + /* + * This indicates that the UDP checksum was + * calculated for the tunnel packet and that the t_l4_cs_error + * field indicates if there was an error. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_L4_CS_CALC UINT32_C(0x8) + /* The field indicates what format the metadata field is. */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_SFT 4 + /* No metadata information. Values are zero. */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the table scope + * and action record pointer. + * + * - metadata2[25:0] contains the action record pointer. + * - metadata2[31:26] contains the table scope. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_ACT_REC_PTR (UINT32_C(0x1) << 4) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the Tunnel ID value, justified + * to LSB. + * + * - VXLAN = VNI[23:0] -> VXLAN Network ID + * - Geneve (NGE) = VNI[23:0] a-> Virtual Network Identifier + * - NVGRE = TNI[23:0] -> Tenant Network ID + * - GRE = KEY[31:0] -> key field with bit mask. zero if K=0 + * - IPv4 = 0 (not populated) + * - IPv6 = Flow Label[19:0] + * - PPPoE = sessionID[15:0] + * - MPLs = Outer label[19:0] + * - UPAR = Selected[31:0] with bit mask + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_TUNNEL_ID (UINT32_C(0x2) << 4) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0],de, vid[11:0]} + * + * The metadata2 field contains the 32b metadata from the + * prepended header (chdr_data). + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_CHDR_DATA (UINT32_C(0x3) << 4) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the outer_l3_offset, + * inner_l2_offset, inner_l3_offset, and inner_l4_size. + * + * - metadata2[8:0] contains the outer_l3_offset. + * - metadata2[17:9] contains the inner_l2_offset. + * - metadata2[26:18] contains the inner_l3_offset. + * - metadata2[31:27] contains the inner_l4_size. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_HDR_OFFSET (UINT32_C(0x4) << 4) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_LAST CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_META_FORMAT_HDR_OFFSET + /* + * This field indicates the IP type for the inner-most IP header. + * A value of '0' indicates IPv4. A value of '1' indicates IPv6. + * This value is only valid if itype indicates a packet + * with an IP header. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_IP_TYPE UINT32_C(0x100) + /* + * This indicates that the complete 1's complement checksum was + * calculated for the packet. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_COMPLETE_CHECKSUM_CALC UINT32_C(0x200) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_TYPE UINT32_C(0x400) + /* Indicates that the Tunnel IP type was IPv4. */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_TYPE_IPV4 (UINT32_C(0x0) << 10) + /* Indicates that the Tunnel IP type was IPv6. */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_TYPE_IPV6 (UINT32_C(0x1) << 10) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_TYPE_LAST CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_T_IP_TYPE_IPV6 + /* + * This value is the complete 1's complement checksum calculated + * from the start of the outer L3 header to the end of the packet + * (not including the ethernet crc). It is valid when the + * 'complete_checksum_calc' flag is set. + */ + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_COMPLETE_CHECKSUM_MASK UINT32_C(0xffff0000) + #define CQ_RES_RAWETH_QP1_V3_RAWETH_QP1_FLAGS2_COMPLETE_CHECKSUM_SFT 16 + /* + * This is data from the CFA block as indicated by the meta_format + * field. + * + * - meta_format 0 - none - metadata2 = 0 - not valid/not stripped + * - meta_format 1 - act_rec_ptr - metadata2 = {table_scope[5:0], + * act_rec_ptr[25:0]} + * - meta_format 2 - tunnel_id - metadata2 = tunnel_id[31:0] + * - meta_format 3 - chdr_data - metadata2 = updated_chdr_data[31:0] + * - meta_format 4 - hdr_offsets - metadata2 = hdr_offsets[31:0] + */ + uint32_t cfa_metadata2; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries. + */ + #define CQ_RES_RAWETH_QP1_V3_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_RES_RAWETH_QP1_V3_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_RES_RAWETH_QP1_V3_CQE_TYPE_SFT 1 + /* + * Responder RawEth and QP1 Completion - This is used for RQ and + * SRQ completion for RawEth service. It is also used for QP1 QPs + * that are treated as RawEth. + */ + #define CQ_RES_RAWETH_QP1_V3_CQE_TYPE_RES_RAWETH_QP1_V3 (UINT32_C(0xb) << 1) + #define CQ_RES_RAWETH_QP1_V3_CQE_TYPE_LAST CQ_RES_RAWETH_QP1_V3_CQE_TYPE_RES_RAWETH_QP1_V3 + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_OK UINT32_C(0x0) + /* + * This indicates that the packet was too long for the WQE provided + * on the SRQ/RQ. + * + * This is not a fatal error. All the fields in the CQE are valid. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x3) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE had already been taken off the RQ/SRQ when a fatal error + * was detected on responder Rx. Only the opaque field in the CQE + * is valid. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_HW_FLUSH_ERR UINT32_C(0xe) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_RES_RAWETH_QP1_V3_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_RES_RAWETH_QP1_V3_STATUS_LAST CQ_RES_RAWETH_QP1_V3_STATUS_OVERFLOW_ERR + uint8_t flags; + /* + * This flag indicates that the completion is for a SRQ entry + * rather than for an RQ entry. + */ + #define CQ_RES_RAWETH_QP1_V3_FLAGS_SRQ UINT32_C(0x1) + /* CQE relates to RQ WQE. */ + #define CQ_RES_RAWETH_QP1_V3_FLAGS_SRQ_RQ UINT32_C(0x0) + /* CQE relates to SRQ WQE. */ + #define CQ_RES_RAWETH_QP1_V3_FLAGS_SRQ_SRQ UINT32_C(0x1) + #define CQ_RES_RAWETH_QP1_V3_FLAGS_SRQ_LAST CQ_RES_RAWETH_QP1_V3_FLAGS_SRQ_SRQ + /* + * This value indicates the offset in bytes from the beginning of the + * packet where the inner payload starts. This value is valid for + * TCP, UDP, FCoE, and RoCE packets. + * + * A value of zero indicates an offset of 256 bytes. + */ + uint8_t raweth_qp1_payload_offset; + /* This value is from the WQE that is being completed. */ + uint32_t opaque; +} cq_res_raweth_qp1_v3_t, *pcq_res_raweth_qp1_v3_t; + +/* + * This is the Responder RQ/SRQ CQE V3 structure for UD QPs and QP1 QPs + * treated as UD. This is used to complete RQ/SRQ WQE's. It differs + * from the Res_UD CQE in that it carries additional CFA fields, in + * place of the QP handle. (Instead of the QP handle, this CQE carries + * the QID. It is up to the user to map the QID back to a QP handle.) + * When the WQE is completed, it indicates that there is room for one + * more WQE on the corresponding RQ/SRQ. + * + * User can determine available space in the RQ/SRQ by comparing + * a rq_cons_idx to a rq_prod_idx, both maintained by the user. The + * range for rq_prod/cons_idx is from 0 to QPC.rq_size-1. The + * rq_prod_idx value increments by one for each WQE that is added to + * the RQ/SRQ by the user. Value must be wrapped at rq_size. The + * rq_cons_idx value increments by one for each WQE that is completed + * from that particular RQ/SRQ. The qp_handle can be used by the user + * to determine what RQ/SRQ to increment. Value must also be wrapped at + * rq_size. When the two values are equal, the RQ/SRQ is empty. When + * (rq_prod_idx+1)%QPC.rq_size==rq_cons_idx, the queue is full. + */ +/* cq_res_ud_cfa_v3 (size:256b/32B) */ + +typedef struct cq_res_ud_cfa_v3 { + uint16_t length; + /* + * The length of the message's payload in bytes, stored in + * the SGEs + */ + #define CQ_RES_UD_CFA_V3_LENGTH_MASK UINT32_C(0x3fff) + #define CQ_RES_UD_CFA_V3_LENGTH_SFT 0 + /* This is data from the CFA as indicated by the meta_format field. */ + uint16_t cfa_metadata0; + /* When meta_format=1, this value is the VLAN VID. */ + #define CQ_RES_UD_CFA_V3_CFA_METADATA0_VID_MASK UINT32_C(0xfff) + #define CQ_RES_UD_CFA_V3_CFA_METADATA0_VID_SFT 0 + /* When meta_format=1, this value is the VLAN DE. */ + #define CQ_RES_UD_CFA_V3_CFA_METADATA0_DE UINT32_C(0x1000) + /* When meta_format=1, this value is the VLAN PRI. */ + #define CQ_RES_UD_CFA_V3_CFA_METADATA0_PRI_MASK UINT32_C(0xe000) + #define CQ_RES_UD_CFA_V3_CFA_METADATA0_PRI_SFT 13 + /* Immediate data in case the imm_flag set. */ + uint32_t imm_data; + uint32_t qid_cfa_metadata1_src_qp_high; + /* + * This value indicates the QPID associated with this operation. + * + * The driver will use the qid from this CQE to map a QP handle + * in the completion record returned to the application. + */ + #define CQ_RES_UD_CFA_V3_QID_MASK UINT32_C(0x7ff) + #define CQ_RES_UD_CFA_V3_QID_SFT 0 + #define CQ_RES_UD_CFA_V3_UNUSED_MASK UINT32_C(0xff800) + #define CQ_RES_UD_CFA_V3_UNUSED_SFT 11 + #define CQ_RES_UD_CFA_V3_CFA_METADATA1_MASK UINT32_C(0xf00000) + #define CQ_RES_UD_CFA_V3_CFA_METADATA1_SFT 20 + /* When meta_format != 0, this value is the VLAN TPID_SEL. */ + #define CQ_RES_UD_CFA_V3_CFA_METADATA1_TPID_SEL_MASK UINT32_C(0x700000) + #define CQ_RES_UD_CFA_V3_CFA_METADATA1_TPID_SEL_SFT 20 + /* When meta_format != 0, this value is the VLAN valid. */ + #define CQ_RES_UD_CFA_V3_CFA_METADATA1_VALID UINT32_C(0x800000) + /* Upper 8b of the Source QP value from the DETH header. */ + #define CQ_RES_UD_CFA_V3_SRC_QP_HIGH_MASK UINT32_C(0xff000000) + #define CQ_RES_UD_CFA_V3_SRC_QP_HIGH_SFT 24 + /* + * This is data from the CFA block as indicated by the meta_format + * field. + * + * - meta_format 0 - none - metadata2 = 0 - not valid/not stripped + * - meta_format 1 - act_rec_ptr - metadata2 = {table_scope[5:0], + * act_rec_ptr[25:0]} + * - meta_format 2 - tunnel_id - metadata2 = tunnel_id[31:0] + * - meta_format 3 - chdr_data - metadata2 = updated_chdr_data[31:0] + * - meta_format 4 - hdr_offsets - metadata2 = hdr_offsets[31:0] + */ + uint32_t cfa_metadata2; + /* + * Source MAC address for the UD message placed in the WQE + * that is completed by this CQE. + */ + uint16_t src_mac[3]; + /* Lower 16b of the Source QP value from the DETH header. */ + uint16_t src_qp_low; + uint8_t cqe_type_toggle; + /* + * Indicate valid completion - written by the chip. The NIC + * toggles this bit each time it finished consuming all PBL + * entries + */ + #define CQ_RES_UD_CFA_V3_TOGGLE UINT32_C(0x1) + /* This field defines the type of CQE. */ + #define CQ_RES_UD_CFA_V3_CQE_TYPE_MASK UINT32_C(0x1e) + #define CQ_RES_UD_CFA_V3_CQE_TYPE_SFT 1 + /* + * Responder UD Completion with CFA - This is used for both RQ + * and SRQ completion for UD service QPs. It includes cfa fields + * (some of which carry VLAN information), in place of the QP + * handle. It is also used for QP1 QPs that are treated as UD. + */ + #define CQ_RES_UD_CFA_V3_CQE_TYPE_RES_UD_CFA_V3 (UINT32_C(0xc) << 1) + #define CQ_RES_UD_CFA_V3_CQE_TYPE_LAST CQ_RES_UD_CFA_V3_CQE_TYPE_RES_UD_CFA_V3 + /* This field indicates the status for the CQE. */ + uint8_t status; + /* The operation completed successfully. */ + #define CQ_RES_UD_CFA_V3_STATUS_OK UINT32_C(0x0) + /* + * This indicates that the packet was too long for the WQE provided + * on the SRQ/RQ. + * + * This is not a fatal error. All the fields in the CQE are valid. + */ + #define CQ_RES_UD_CFA_V3_STATUS_HW_LOCAL_LENGTH_ERR UINT32_C(0x3) + /* + * An internal QP consistency error was detected while processing + * this Work Request. For requester, this could be an SQ WQE format + * error or an operation specified in the WQE that is not supported + * for the QP. For responder, this is an RQ/SRQ WQE format error. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_UD_CFA_V3_STATUS_LOCAL_QP_OPERATION_ERR UINT32_C(0x4) + /* + * An SGE in the locally posted WQE does not reference a Memory + * Region that is valid for the requested operation. If this error + * is generated for an SGE using the reserved l_key, this means + * that the reserved l_key is not enabled. + * + * This is a fatal error detected by the requester Tx or responder + * Rx. For responder CQEs, only the opaque field is valid. + */ + #define CQ_RES_UD_CFA_V3_STATUS_LOCAL_PROTECTION_ERR UINT32_C(0x5) + /* + * A WQE was in process or outstanding when the QP transitioned + * into the Error State. + */ + #define CQ_RES_UD_CFA_V3_STATUS_WORK_REQUEST_FLUSHED_ERR UINT32_C(0xd) + /* + * A WQE had already been taken off the RQ/SRQ when a fatal error + * was detected on responder Rx. Only the opaque field in the CQE + * is valid. + */ + #define CQ_RES_UD_CFA_V3_STATUS_HW_FLUSH_ERR UINT32_C(0xe) + /* + * A WQE was posted to the SQ/RQ that caused it to overflow. For + * requester CQEs, it was the SQ that overflowed. For responder + * CQEs, it was the RQ that overflowed. + */ + #define CQ_RES_UD_CFA_V3_STATUS_OVERFLOW_ERR UINT32_C(0xf) + #define CQ_RES_UD_CFA_V3_STATUS_LAST CQ_RES_UD_CFA_V3_STATUS_OVERFLOW_ERR + uint16_t flags; + /* + * This flag indicates that the completion is for a SRQ entry + * rather than for an RQ entry. + */ + #define CQ_RES_UD_CFA_V3_FLAGS_SRQ UINT32_C(0x1) + /* CQE relates to RQ WQE. */ + #define CQ_RES_UD_CFA_V3_FLAGS_SRQ_RQ UINT32_C(0x0) + /* CQE relates to SRQ WQE. */ + #define CQ_RES_UD_CFA_V3_FLAGS_SRQ_SRQ UINT32_C(0x1) + #define CQ_RES_UD_CFA_V3_FLAGS_SRQ_LAST CQ_RES_UD_CFA_V3_FLAGS_SRQ_SRQ + /* Immediate data indicator */ + #define CQ_RES_UD_CFA_V3_FLAGS_IMM UINT32_C(0x2) + #define CQ_RES_UD_CFA_V3_FLAGS_UNUSED_MASK UINT32_C(0xc) + #define CQ_RES_UD_CFA_V3_FLAGS_UNUSED_SFT 2 + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_MASK UINT32_C(0x30) + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_SFT 4 + /* RoCEv1 Message */ + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_V1 (UINT32_C(0x0) << 4) + /* RoCEv2 IPv4 Message */ + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_V2IPV4 (UINT32_C(0x2) << 4) + /* RoCEv2 IPv6 Message */ + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_V2IPV6 (UINT32_C(0x3) << 4) + #define CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_LAST CQ_RES_UD_CFA_V3_FLAGS_ROCE_IP_VER_V2IPV6 + /* The field indicates what format the metadata field is. */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_MASK UINT32_C(0x3c0) + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_SFT 6 + /* No metadata information. Value is zero. */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_NONE (UINT32_C(0x0) << 6) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the table scope + * and action record pointer. + * + * - metadata2[25:0] contains the action record pointer. + * - metadata2[31:26] contains the table scope. + */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_ACT_REC_PTR (UINT32_C(0x1) << 6) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the Tunnel ID + * value, justified to LSB. + * + * - VXLAN = VNI[23:0] -> VXLAN Network ID + * - Geneve (NGE) = VNI[23:0] a-> Virtual Network Identifier + * - NVGRE = TNI[23:0] -> Tenant Network ID + * - GRE = KEY[31:0] -> key field with bit mask. zero if K=0 + * - IPv4 = 0 (not populated) + * - IPv6 = Flow Label[19:0] + * - PPPoE = sessionID[15:0] + * - MPLs = Outer label[19:0] + * - UPAR = Selected[31:0] with bit mask + */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_TUNNEL_ID (UINT32_C(0x2) << 6) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0],de, vid[11:0]} + * + * The metadata2 field contains the 32b metadata from the + * prepended header (chdr_data). + */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_CHDR_DATA (UINT32_C(0x3) << 6) + /* + * The {metadata1, metadata0} fields contain the vtag + * information: + * + * - vtag[19:0] = {valid, tpid_sel[2:0], pri[2:0], de, vid[11:0]} + * + * The metadata2 field contains the outer_l3_offset, + * inner_l2_offset, inner_l3_offset, and inner_l4_size. + * + * - metadata2[8:0] contains the outer_l3_offset. + * - metadata2[17:9] contains the inner_l2_offset. + * - metadata2[26:18] contains the inner_l3_offset. + * - metadata2[31:27] contains the inner_l4_size. + */ + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_HDR_OFFSET (UINT32_C(0x4) << 6) + #define CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_LAST CQ_RES_UD_CFA_V3_FLAGS_META_FORMAT_HDR_OFFSET + /* + * This value will be returned in the completion if the completion is + * signaled. + */ + uint32_t opaque; +} cq_res_ud_cfa_v3_t, *pcq_res_ud_cfa_v3_t; + /* nq_base (size:128b/16B) */ typedef struct nq_base { @@ -74648,8 +87973,8 @@ typedef struct nq_base { /* * This field indicates the exact type of the completion. * By convention, the LSB identifies the length of the - * record in 16B units. Even values indicate 16B - * records. Odd values indicate 32B + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B * records. */ #define NQ_BASE_TYPE_MASK UINT32_C(0x3f) @@ -74664,7 +87989,9 @@ typedef struct nq_base { #define NQ_BASE_TYPE_QP_EVENT UINT32_C(0x38) /* Function Async Notification */ #define NQ_BASE_TYPE_FUNC_EVENT UINT32_C(0x3a) - #define NQ_BASE_TYPE_LAST NQ_BASE_TYPE_FUNC_EVENT + /* NQ Reassign Notification */ + #define NQ_BASE_TYPE_NQ_REASSIGN UINT32_C(0x3c) + #define NQ_BASE_TYPE_LAST NQ_BASE_TYPE_NQ_REASSIGN /* info10 is 10 b */ #define NQ_BASE_INFO10_MASK UINT32_C(0xffc0) #define NQ_BASE_INFO10_SFT 6 @@ -74676,8 +88003,8 @@ typedef struct nq_base { uint64_t info63_v; /* * This value is written by the NIC such that it will be different - * for each pass through the completion queue. The even passes - * will write 1. The odd passes will write 0. + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. */ #define NQ_BASE_V UINT32_C(0x1) /* info63 is 63 b */ @@ -74693,8 +88020,8 @@ typedef struct nq_cn { /* * This field indicates the exact type of the completion. * By convention, the LSB identifies the length of the - * record in 16B units. Even values indicate 16B - * records. Odd values indicate 32B + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B * records. */ #define NQ_CN_TYPE_MASK UINT32_C(0x3f) @@ -74706,25 +88033,31 @@ typedef struct nq_cn { * This field carries the toggle value that must be used to * re-arm this CQ. The toggle value should be copied into the * doorbell used to CQ_ARMENA, CQ_ARMALL or CQ_ARMSE doorbells. + * + * This value is used by HW to detect old and stale CQ_ARMENA, + * CQ_ARMALL, or CQ_ARMSE doorbells that are caused by having + * a backup doorbell location or by PCI or other reordering + * problems. Only the doorbells that match the latest value of + * toggle will be honored. */ #define NQ_CN_TOGGLE_MASK UINT32_C(0xc0) #define NQ_CN_TOGGLE_SFT 6 uint16_t reserved16; /* * This is an application level ID used to identify the - * CQ. This field carries the lower 32b of the value. + * CQ. This field carries the lower 32b of the value. */ uint32_t cq_handle_low; uint32_t v; /* * This value is written by the NIC such that it will be different - * for each pass through the completion queue. The even passes - * will write 1. The odd passes will write 0. + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. */ #define NQ_CN_V UINT32_C(0x1) /* * This is an application level ID used to identify the - * CQ. This field carries the upper 32b of the value. + * CQ. This field carries the upper 32b of the value. */ uint32_t cq_handle_high; } nq_cn_t, *pnq_cn_t; @@ -74737,9 +88070,8 @@ typedef struct nq_srq_event { /* * This field indicates the exact type of the completion. * By convention, the LSB identifies the length of the - * record in 16B units. Even values indicate 16B - * records. Odd values indicate 32B - * records. + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B records. */ #define NQ_SRQ_EVENT_TYPE_MASK UINT32_C(0x3f) #define NQ_SRQ_EVENT_TYPE_SFT 0 @@ -74764,20 +88096,20 @@ typedef struct nq_srq_event { uint16_t reserved16; /* * This is the SRQ handle value for the queue that has - * reached it's event threshold. This field carries the + * reached it's event threshold. This field carries the * lower 32b of the value. */ uint32_t srq_handle_low; uint32_t v; /* * This value is written by the NIC such that it will be different - * for each pass through the completion queue. The even passes - * will write 1. The odd passes will write 0. + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. */ #define NQ_SRQ_EVENT_V UINT32_C(0x1) /* * This is the SRQ handle value for the queue that has - * reached it's event threshold. This field carries the + * reached it's event threshold. This field carries the * upper 32b of the value. */ uint32_t srq_handle_high; @@ -74791,8 +88123,8 @@ typedef struct nq_dbq_event { /* * This field indicates the exact type of the completion. * By convention, the LSB identifies the length of the - * record in 16B units. Even values indicate 16B - * records. Odd values indicate 32B + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B * records. */ #define NQ_DBQ_EVENT_TYPE_MASK UINT32_C(0x3f) @@ -74826,14 +88158,14 @@ typedef struct nq_dbq_event { uint32_t v; /* * This value is written by the NIC such that it will be different - * for each pass through the completion queue. The even passes - * will write 1. The odd passes will write 0. + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. */ #define NQ_DBQ_EVENT_V UINT32_C(0x1) uint32_t db_type_db_xid; /* * DB 'XID' field from doorbell that crossed the async event - * threshold. This is a QPID, SID, or CID, depending on + * threshold. This is a QPID, SID, or CID, depending on * the db_type field. */ #define NQ_DBQ_EVENT_DB_XID_MASK UINT32_C(0xfffff) @@ -74846,6 +88178,46 @@ typedef struct nq_dbq_event { #define NQ_DBQ_EVENT_DB_TYPE_SFT 28 } nq_dbq_event_t, *pnq_dbq_event_t; +/* + * This completion indicates that the NQ Reassign doorbell has been + * executed by the CQ processing block and no further NQE will arrive + * for this CQ on this NQ. + */ +/* nq_reassign (size:128b/16B) */ + +typedef struct nq_reassign { + uint16_t type; + /* + * This field indicates the exact type of the completion. + * By convention, the LSB identifies the length of the + * record in 16B units. Even values indicate 16B + * records. Odd values indicate 32B records. + */ + #define NQ_REASSIGN_TYPE_MASK UINT32_C(0x3f) + #define NQ_REASSIGN_TYPE_SFT 0 + /* NQ Reassign Notification */ + #define NQ_REASSIGN_TYPE_NQ_REASSIGN UINT32_C(0x3c) + #define NQ_REASSIGN_TYPE_LAST NQ_REASSIGN_TYPE_NQ_REASSIGN + uint16_t reserved16; + /* + * This is an application level ID used to identify the + * CQ. This field carries the lower 32b of the value. + */ + uint32_t cq_handle_low; + uint32_t v; + /* + * This value is written by the NIC such that it will be different + * for each pass through the completion queue. The even passes + * will write 1. The odd passes will write 0. + */ + #define NQ_REASSIGN_V UINT32_C(0x1) + /* + * This is an application level ID used to identify the + * CQ. This field carries the upper 32b of the value. + */ + uint32_t cq_handle_high; +} nq_reassign_t, *pnq_reassign_t; + /* Input Read Request Queue (IRRQ) Message */ /* xrrq_irrq (size:256b/32B) */ @@ -74874,9 +88246,9 @@ typedef struct xrrq_irrq { uint32_t msn; /* * The value of QPC.pending_ack_msn after it is incremented as a - * result of receiving the read/atomic request. IRRQ.msn-1 will be - * placed in the MSN field of the first response and IRRQ.msn will - * placed in the MSN field of the last or only response. + * result of receiving the read/atomic request. IRRQ.msn-1 will + * be placed in the MSN field of the first response and IRRQ.msn + * will placed in the MSN field of the last or only response. */ #define XRRQ_IRRQ_MSN_MASK UINT32_C(0xffffff) #define XRRQ_IRRQ_MSN_SFT 0 @@ -74892,7 +88264,10 @@ typedef struct xrrq_irrq { uint64_t va_or_atomic_result; /* The key to the MR/W in the request */ uint32_t rdma_r_key; - /* Length in bytes of the data requested. Length must be 8 if type is atomic. */ + /* + * Length in bytes of the data requested. Length must be 8 if type is + * atomic. + */ uint32_t length; } xrrq_irrq_t, *pxrrq_irrq_t; @@ -74921,18 +88296,21 @@ typedef struct xrrq_orrq { * If num_sges is 2 or more for an RDMA Read request, then * the first_sge_phy_or_sing_sge_va field carries the * physical address in host memory where the first sge is - * stored. The single_sge_l_key and single_sge_size fields + * stored. The single_sge_l_key and single_sge_size fields * are unused in this case. * * A special case is a zero-length, zero-sge RDMA read request - * WQE. In this situation, num_sges will be 1. However, + * WQE. In this situation, num_sges will be 1. However, * first_sge_phy_or_sing_sge_va, single_sge_l_key, and * single_sge_size will all be populated with zeros. */ #define XRRQ_ORRQ_NUM_SGES_MASK UINT32_C(0xf800) #define XRRQ_ORRQ_NUM_SGES_SFT 11 uint16_t reserved16; - /* Length in bytes of the data requested. Length must be 8 if type is atomic. */ + /* + * Length in bytes of the data requested. Length must be 8 if type is + * atomic. + */ uint32_t length; uint32_t psn; /* The PSN of the outstanding outgoing request */ @@ -74968,25 +88346,25 @@ typedef struct xrrq_orrq { typedef struct ptu_pte { uint64_t page_next_to_last_last_valid; /* - * This field indicates if the PTE is valid. A value of '0' - * indicates that the page is not valid. A value of '1' - * indicates that the page is valid. A reference to an + * This field indicates if the PTE is valid. A value of '0' + * indicates that the page is not valid. A value of '1' + * indicates that the page is valid. A reference to an * invalid page will return a PTU error. */ #define PTU_PTE_VALID UINT32_C(0x1) /* * This field is used only for "ring" PBLs that are used for - * SQ, RQ, SRQ, or CQ structures. For all other PBL structures, - * this bit should be zero. When this bit is '1', it indicates + * SQ, RQ, SRQ, or CQ structures. For all other PBL structures, + * this bit should be zero. When this bit is '1', it indicates * that the page pointed to by this PTE is the last page in the - * ring. A prefetch for the ring should use the first PTE in + * ring. A prefetch for the ring should use the first PTE in * the PBL. */ #define PTU_PTE_LAST UINT32_C(0x2) /* * This field is used only for "ring" PBLs that are used for - * SQ, RQ, SRQ, or CQ structures. For all other PBL structures, - * this bit should be zero. When this bit is '1', it indicates + * SQ, RQ, SRQ, or CQ structures. For all other PBL structures, + * this bit should be zero. When this bit is '1', it indicates * that this is the next-to-last page of the PBL. */ #define PTU_PTE_NEXT_TO_LAST UINT32_C(0x4) @@ -74995,10 +88373,10 @@ typedef struct ptu_pte { #define PTU_PTE_UNUSED_SFT 3 /* * This is the upper bits of the physical page controlled by - * this PTE. If the page is larger than 4KB, then the unused + * this PTE. If the page is larger than 4KB, then the unused * lower bits of the page address should be zero. */ - #define PTU_PTE_PAGE_MASK UINT32_C(0xfffff000) + #define PTU_PTE_PAGE_MASK UINT32_C(0xfffffffffffff000)L #define PTU_PTE_PAGE_SFT 12 } ptu_pte_t, *pptu_pte_t; @@ -75008,9 +88386,9 @@ typedef struct ptu_pte { typedef struct ptu_pde { uint64_t page_valid; /* - * This field indicates if the PTE is valid. A value of '0' - * indicates that the page is not valid. A value of '1' - * indicates that the page is valid. A reference to an + * This field indicates if the PTE is valid. A value of '0' + * indicates that the page is not valid. A value of '1' + * indicates that the page is valid. A reference to an * invalid page will return a PTU error. */ #define PTU_PDE_VALID UINT32_C(0x1) @@ -75019,15 +88397,15 @@ typedef struct ptu_pde { #define PTU_PDE_UNUSED_SFT 1 /* * This is the upper bits of the physical page controlled by - * this PTE. If the page is larger than 4KB, then the unused + * this PTE. If the page is larger than 4KB, then the unused * lower bits of the page address should be zero. */ - #define PTU_PDE_PAGE_MASK UINT32_C(0xfffff000) + #define PTU_PDE_PAGE_MASK UINT32_C(0xfffffffffffff000)L #define PTU_PDE_PAGE_SFT 12 } ptu_pde_t, *pptu_pde_t; /* - * This is the 64b doorbell format. The host writes this message + * This is the 64b doorbell format. The host writes this message * format directly to byte offset 0 of the appropriate doorbell page. */ /* dbc_dbc (size:64b/8B) */ @@ -75067,11 +88445,11 @@ typedef struct dbc_dbc { /* * The toggle value is used in CQ_ARMENA, CQ_ARMSE, CQ_ARMALL, * SRQ_ARMENA, SRQ_ARM, and CQ_CUTOFF_ACK doorbells to qualify the - * doorbell as valid. This value should be taken from the latest + * doorbell as valid. This value should be taken from the latest * NQE or cutoff completion. * * Doorbells of the above types with the wrong toggle value will - * be ignored. This is how old values in of backup doorbells + * be ignored. This is how old values in of backup doorbells * are ignored. */ #define DBC_DBC_TOGGLE_MASK UINT32_C(0x6000000) @@ -75081,7 +88459,7 @@ typedef struct dbc_dbc { * This value identifies the resource that the doorbell is intended * to notify. * - * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For + * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For * CQ, this is the CID. For NQ, this is the NID. * * Bits [19:16] of this values must be zero for a SID value. @@ -75119,20 +88497,20 @@ typedef struct dbc_dbc { #define DBC_DBC_TYPE_MASK UINT32_C(0xf0000000) #define DBC_DBC_TYPE_SFT 28 /* - * This is a SQ producer index update. It indicates one or more + * This is a SQ producer index update. It indicates one or more * new entries have been written to the SQ for the QPID indicated * on the xID field. This type is valid for L2, RoCE and Engine * path. */ #define DBC_DBC_TYPE_SQ (UINT32_C(0x0) << 28) /* - * This is a RQ producer index update. It indicates one or more + * This is a RQ producer index update. It indicates one or more * new entries have been written to the RQ for the QPID indicated * on the xID field. This type is valid for RoCE path. */ #define DBC_DBC_TYPE_RQ (UINT32_C(0x1) << 28) /* - * This is a SRQ producer index update. It indicates one or more + * This is a SRQ producer index update. It indicates one or more * new entries have been written to the SRQ for the SID indicated * on the xID field. This type is valid for L2 and RoCE path. */ @@ -75146,7 +88524,7 @@ typedef struct dbc_dbc { */ #define DBC_DBC_TYPE_SRQ_ARM (UINT32_C(0x3) << 28) /* - * This is a CQ consumer index update. It indicates one or more + * This is a CQ consumer index update. It indicates one or more * entries have been processed off the CQ indicated on the xID * field.This type is valid for L2, RoCE and Engine path. */ @@ -75163,7 +88541,7 @@ typedef struct dbc_dbc { */ #define DBC_DBC_TYPE_CQ_ARMALL (UINT32_C(0x6) << 28) /* - * This is a CQ arm enable message. This message must be sent + * This is a CQ arm enable message. This message must be sent * from the privileged driver before a new CQ_ARMSE or CQ_ARMALL * message will be accepted. * @@ -75173,7 +88551,7 @@ typedef struct dbc_dbc { #define DBC_DBC_TYPE_CQ_ARMENA (UINT32_C(0x7) << 28) /* * This doorbell command enables the SRQ async event - * to be armed. This message must be sent from the privileged + * to be armed. This message must be sent from the privileged * driver before a new SRQ_ARM message will be accepted. * The xID field must identify the SID that is begin enabled * for arm. @@ -75222,7 +88600,202 @@ typedef struct dbc_dbc { } dbc_dbc_t, *pdbc_dbc_t; /* - * This is the 32b doorbell format. The host writes this message + * This is the 64b doorbell copy format. The host writes this DB to + * the doorbell copy memory. Upon a HW Doorbell Drop Recovery process, + * it would be DMAed into HW for recovering the dropped doorbell. + */ +/* dbc_dbc64 (size:64b/8B) */ + +typedef struct dbc_dbc64 { + uint64_t dbc; + /* + * This value is the index being written. + * + * For SQ, RQ, and SRQ, this is the producer index and the unit is + * 16B of queue space for L2 path and for the Engine path. For RoCE + * path there is a legacy mode with 128B unit size and a variable + * size WQE mode with 16B unit size of queue space. This mode is + * configured in the QP. + * + * For CQ this is the consumer index and the unit is 32B of queue + * space for the RoCE/Engine path and the CQ index unit is 16B of + * queue space for the L2 path. + * + * For NQ this is the consumer index and the unit is always 16B of + * queue space. + * + * The index size is 24b for L2 and engine paths and 16b for the + * RoCE path. Unused bits should be written as zero. + */ + #define DBC_DBC64_INDEX_MASK UINT32_C(0xffffff) + #define DBC_DBC64_INDEX_SFT 0 + /* + * The epoch bit provides a frame of reference for the queue index. + * S/W will toggle this bit in the doorbell each time index range is + * wrapped. This allows the receiving HW block to more efficiently + * detect out-of-order doorbells and to ignore the older doorbells. + * Out-of-order doorbells occur normally during dropped doorbell + * recovery. + */ + #define DBC_DBC64_EPOCH UINT32_C(0x1000000) + /* + * The toggle value is used in CQ_ARMENA, CQ_ARMSE, CQ_ARMALL, + * SRQ_ARMENA, SRQ_ARM, and CQ_CUTOFF_ACK doorbells to qualify the + * doorbell as valid. This value should be taken from the latest + * NQE or cutoff completion. + * + * Doorbells of the above types with the wrong toggle value will + * be ignored. This is how old values in of backup doorbells + * are ignored. + */ + #define DBC_DBC64_TOGGLE_MASK UINT32_C(0x6000000) + #define DBC_DBC64_TOGGLE_SFT 25 + /* + * This value identifies the resource that the doorbell is intended + * to notify. + * + * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For + * CQ, this is the CID. For NQ, this is the NID. + * + * Bits [51:48] of this values must be zero for a SID value. + */ + #define DBC_DBC64_XID_MASK UINT32_C(0xfffff00000000)L + #define DBC_DBC64_XID_SFT 32 + /* + * This value defines the intended doorbell path between RoCE and + * L2. + */ + #define DBC_DBC64_PATH_MASK UINT32_C(0x300000000000000)L + #define DBC_DBC64_PATH_SFT 56 + /* This is a RoCE doorbell message. */ + #define DBC_DBC64_PATH_ROCE (UINT32_C(0x0)L << 56) + /* This is a L2 doorbell message. */ + #define DBC_DBC64_PATH_L2 (UINT32_C(0x1)L << 56) + /* Engine path doorbell. */ + #define DBC_DBC64_PATH_ENGINE (UINT32_C(0x2)L << 56) + #define DBC_DBC64_PATH_LAST DBC_DBC64_PATH_ENGINE + /* + * This indicates it is valid doorbell update. It should be set for + * each doorbell written to the chip and set when doorbell message is + * written to the backup doorbell location. The bit should be cleared + * in the backup doorbell location at time zero to indicate that the + * backup doorbell has not yet been written. + */ + #define DBC_DBC64_VALID UINT32_C(0x400000000000000)L + /* + * When this bit is set to one, the chip will capture debug + * information for the doorbell ring. This is intended to only be + * used on SQ doorbell rings. + */ + #define DBC_DBC64_DEBUG_TRACE UINT32_C(0x800000000000000)L + /* This value identifies the type of doorbell being written. */ + #define DBC_DBC64_TYPE_MASK UINT32_C(0xf000000000000000)L + #define DBC_DBC64_TYPE_SFT 60 + /* + * This is a SQ producer index update. It indicates one or more + * new entries have been written to the SQ for the QPID indicated + * on the xID field. This type is valid for L2, RoCE and Engine + * path. + */ + #define DBC_DBC64_TYPE_SQ (UINT32_C(0x0)L << 60) + /* + * This is a RQ producer index update. It indicates one or more + * new entries have been written to the RQ for the QPID indicated + * on the xID field. This type is valid for RoCE path. + */ + #define DBC_DBC64_TYPE_RQ (UINT32_C(0x1)L << 60) + /* + * This is a SRQ producer index update. It indicates one or more + * new entries have been written to the SRQ for the SID indicated + * on the xID field. This type is valid for L2 and RoCE path. + */ + #define DBC_DBC64_TYPE_SRQ (UINT32_C(0x2)L << 60) + /* + * This doorbell command arms the SRQ async event. + * The xID field must identify the SID that is begin armed. + * The index field is will set the arm threshold such that + * a notification will be generated if less than that number + * or SRQ entries are posted. This type is valid for RoCE path. + */ + #define DBC_DBC64_TYPE_SRQ_ARM (UINT32_C(0x3)L << 60) + /* + * This is a CQ consumer index update. It indicates one or more + * entries have been processed off the CQ indicated on the xID + * field.This type is valid for L2, RoCE and Engine path. + */ + #define DBC_DBC64_TYPE_CQ (UINT32_C(0x4)L << 60) + /* + * this is a CQ consumer index update that also arms the CQ for + * solicited events. This type is valid for RoCE path. + */ + #define DBC_DBC64_TYPE_CQ_ARMSE (UINT32_C(0x5)L << 60) + /* + * This is a CQ consumer index update that also arms the CQ + * for any new CQE. This type is valid for L2, RoCE and Engine + * path. + */ + #define DBC_DBC64_TYPE_CQ_ARMALL (UINT32_C(0x6)L << 60) + /* + * This is a CQ arm enable message. This message must be sent + * from the privileged driver before a new CQ_ARMSE or CQ_ARMALL + * message will be accepted. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_DBC64_TYPE_CQ_ARMENA (UINT32_C(0x7)L << 60) + /* + * This doorbell command enables the SRQ async event + * to be armed. This message must be sent from the privileged + * driver before a new SRQ_ARM message will be accepted. + * The xID field must identify the SID that is begin enabled + * for arm. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_DBC64_TYPE_SRQ_ARMENA (UINT32_C(0x8)L << 60) + /* + * This doorbell command indicates that the cutoff CQE has + * been processed and the driver is now processing completions + * from the new CQ. + * + * The index field for this doorbell type must be zero. + */ + #define DBC_DBC64_TYPE_CQ_CUTOFF_ACK (UINT32_C(0x9)L << 60) + /* + * This is a NQ consumer index update. It indicates one or more + * entries have been processed off the NQ indicated on the xID + * field. This type is valid for L2, RoCE and Engine path. + */ + #define DBC_DBC64_TYPE_NQ (UINT32_C(0xa)L << 60) + /* + * This is a NQ consumer index update that also arms the NQ for + * any new NQE. This type is valid for L2, RoCE and Engine path. + */ + #define DBC_DBC64_TYPE_NQ_ARM (UINT32_C(0xb)L << 60) + /* + * This is a NQ consumer index update that also arms the NQ for + * any new NQE. It is used for the legacy INT mask. This type + * is valid for L2, RoCE and Engine path. + */ + #define DBC_DBC64_TYPE_NQ_MASK (UINT32_C(0xe)L << 60) + /* + * This doorbell command is used during doorbell moderation + * to consume system BW and help prevent doorbell FIFO + * overflow. + * + * All other fields should be zero for NULL doorbell. + * For doorbell recovery, NULL doorbell type in the Application + * table indicates that it is the last QP entry for the function. + * This type is valid for L2, RoCE and Engine path. + */ + #define DBC_DBC64_TYPE_NULL (UINT32_C(0xf)L << 60) + #define DBC_DBC64_TYPE_LAST DBC_DBC64_TYPE_NULL +} dbc_dbc64_t, *pdbc_dbc64_t; + +/* + * This is the 32b doorbell format. The host writes this message * format directly to byte offset 8 of the appropriate doorbell page. */ /* dbc_dbc32 (size:32b/4B) */ @@ -75233,7 +88806,7 @@ typedef struct dbc_dbc32 { * This value identifies the resource that the doorbell is intended * to notify. * - * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For + * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For * CQ, this is the CID. * * Bits [19:16] of this values must be zero for a SID value. @@ -75255,8 +88828,8 @@ typedef struct dbc_dbc32 { * When abs=0, this value is the value to add to the appropriate * index value. * - * When abs=1, this value is the new value for the index. Absolute - * value is used when the queue is being wrapped. When abs=1, + * When abs=1, this value is the new value for the index. Absolute + * value is used when the queue is being wrapped. When abs=1, * the incr value follows the same rules as the index value * in the 64b doorbell. */ @@ -75268,46 +88841,47 @@ typedef struct dbc_dbc32 { #define DBC_DBC32_TYPE_MASK UINT32_C(0xe0000000) #define DBC_DBC32_TYPE_SFT 29 /* - * This is a SQ producer index update. It indicates one or more - * new entries have been written to the SQ for the QPID indicated - * on the xID field. + * This is a SQ producer index update. It indicates one or more + * new entries have been written to the SQ for the QPID + * indicated on the xID field. */ #define DBC_DBC32_TYPE_SQ (UINT32_C(0x0) << 29) #define DBC_DBC32_TYPE_LAST DBC_DBC32_TYPE_SQ } dbc_dbc32_t, *pdbc_dbc32_t; /* - * This is the 64b Push Start doorbell format. The host writes this message - * format directly to offset of each push associated WCB (write combine - * buffer) within doorbell page. WCB#0 = offset 16, WCB#1 = offset 24, - * WCB#2 = offset 32, ... The start doorbell is followed by write combining - * data to the WCB and then that is followed by a end doorbell. + * This is the 64b Push Start doorbell format. The host writes this + * message format directly to offset of each push associated WCB (write + * combine buffer) within doorbell page. WCB#0 = offset 16, WCB#1 = + * offset 24, WCB#2 = offset 32, ... The start doorbell is followed by + * write combining data to the WCB and then that is followed by a end + * doorbell. */ /* db_push_start (size:64b/8B) */ typedef struct db_push_start { uint64_t db; /* - * This is the push index and should be the SQ slot index, aligned - * to the start of the corresponding push WQE/packet in the Send - * Queue. + * This is the push index and should be the SQ slot index, + * aligned to the start of the corresponding push WQE/packet in + * the Send Queue. * * The index size is 16b for RoCE path and 24b for L2 and Engine * paths. Any unused bits should be written as zero. * * The index unit is 16B for L2 path. For RoCE there is a legacy - * mode with 128B unit size and a variable size mode with 16B unit - * size. For Engine mode, the unit size is 16B, where RQEs are - * always 128B - so it always increments by eight 16B slots per - * RQE. - * - * > This field is not used by the older versions of the chip, but - * > is used in this and future revisions of the chip. In older - * > versions of the chip, the driver is required to complete the - * > push doorbell operation by following it with a regular doorbell - * > which will be used to properly increment the producer index. - * > This extra doorbell write is not needed on this and future - * > versions of the chip. + * mode with 128B unit size and a variable size mode with 16B + * unit size. For Engine mode, the unit size is 16B, where RQEs + * are always 128B - so it always increments by eight 16B slots + * per RQE. + * + * > This field is not used by the older versions of the chip, + * > but is used in this and future revisions of the chip. In + * > older versions of the chip, the driver is required to + * > complete the push doorbell operation by following it with a + * > regular doorbell which will be used to properly increment + * > the producer index. This extra doorbell write is not needed + * > on this and future versions of the chip. */ #define DB_PUSH_START_DB_INDEX_MASK UINT32_C(0xffffff) #define DB_PUSH_START_DB_INDEX_SFT 0 @@ -75319,8 +88893,8 @@ typedef struct db_push_start { #define DB_PUSH_START_DB_PI_LO_MASK UINT32_C(0xff000000) #define DB_PUSH_START_DB_PI_LO_SFT 24 /* - * This value identifies the resource that the doorbell is intended - * to notify. + * This value identifies the resource that the doorbell is + * intended to notify. * * This is the QPID. */ @@ -75338,14 +88912,14 @@ typedef struct db_push_start { #define DB_PUSH_START_DB_TYPE_SFT 60 /* * This is a SQ producer index update for Push. It indicates - * one or more new entries have been written to the SQ for the - * QPID indicated on the `xid` field. + * one or more new entries have been written to the SQ for + * the QPID indicated on the `xid` field. */ #define DB_PUSH_START_DB_TYPE_PUSH_START (UINT32_C(0xc)L << 60) /* * This is a SQ producer index update for Push. It indicates - * one or more new entries have been written to the SQ for the - * QPID indicated on the `xid` field. + * one or more new entries have been written to the SQ for + * the QPID indicated on the `xid` field. */ #define DB_PUSH_START_DB_TYPE_PUSH_END (UINT32_C(0xd)L << 60) #define DB_PUSH_START_DB_TYPE_LAST DB_PUSH_START_DB_TYPE_PUSH_END @@ -75355,32 +88929,33 @@ typedef struct db_push_start { * This is the 64b Push End doorbell format. The host writes this message * format directly to offset of each push associated WCB (write combine * buffer) within doorbell page. WCB#0 = offset 16, WCB#1 = offset 24, - * WCB#2 = offset 32, ... The start doorbell is followed by write combining - * data to the WCB and then that is followed by a end doorbell. + * WCB#2 = offset 32, ... The start doorbell is followed by write + * combining data to the WCB and then that is followed by a end doorbell. */ /* db_push_end (size:64b/8B) */ typedef struct db_push_end { uint64_t db; /* - * This is the producer index and should be the queue index of the - * last WQE written plus the length field contained in that WQE. - * For example, if the length is 8 index units and the WQE was - * written to the first location in the queue (zero), this index - * should be written to 8. The index should point to the start of - * the first location that has not been filled in with WQE data. + * This is the producer index and should be the queue index of + * the last WQE written plus the length field contained in that + * WQE. For example, if the length is 8 index units and the WQE + * was written to the first location in the queue (zero), this + * index should be written to 8. The index should point to the + * start of the first location that has not been filled in with + * WQE data. * - * For L2 and Engine SQ, the index unit is 16B. For RoCE there are - * two modes. For Legacy fixed size RQE mode, the unit is 128B. For - * variable size RQE mode, the unit is 16B. + * For L2 and Engine SQ, the index unit is 16B. For RoCE there + * are two modes. For Legacy fixed size RQE mode, the unit is + * 128B. For variable size RQE mode, the unit is 16B. * * The index size is 24b for L2 and engine paths and 16b for the * RoCE path. Unused bits should be written as zero. * - * > In past revisions of this chip, this field was the push index - * > rather than the producer index. For this version of the chip - * > and future versions of the chip, this field must be the - * > producer index, as described above. + * > In past revisions of this chip, this field was the push + * > index rather than the producer index. For this version of + * > the chip and future versions of the chip, this field must be + * > the producer index, as described above. * > * > Also, in past revisions of this chip, an additional * > doorbell write was needed to communicate the producer index. @@ -75397,8 +88972,8 @@ typedef struct db_push_end { #define DB_PUSH_END_DB_PI_LO_MASK UINT32_C(0xff000000) #define DB_PUSH_END_DB_PI_LO_SFT 24 /* - * This value identifies the resource that the doorbell is intended - * to notify. + * This value identifies the resource that the doorbell is + * intended to notify. * * This is the QPID. */ @@ -75435,14 +89010,14 @@ typedef struct db_push_end { #define DB_PUSH_END_DB_TYPE_SFT 60 /* * This is a SQ producer index update for Push. It indicates - * one or more new entries have been written to the SQ for the - * QPID indicated on the `xid` field. + * one or more new entries have been written to the SQ for + * the QPID indicated on the `xid` field. */ #define DB_PUSH_END_DB_TYPE_PUSH_START (UINT32_C(0xc)L << 60) /* * This is a SQ producer index update for Push. It indicates - * one or more new entries have been written to the SQ for the - * QPID indicated on the `xid` field. + * one or more new entries have been written to the SQ for + * the QPID indicated on the `xid` field. */ #define DB_PUSH_END_DB_TYPE_PUSH_END (UINT32_C(0xd)L << 60) #define DB_PUSH_END_DB_TYPE_LAST DB_PUSH_END_DB_TYPE_PUSH_END @@ -75540,14 +89115,19 @@ typedef struct dbc_absolute_db_32 { * Out-of-order doorbells occur normally during dropped doorbell * recovery. */ - #define DBC_ABSOLUTE_DB_32_EPOCH UINT32_C(0x10000) + #define DBC_ABSOLUTE_DB_32_EPOCH UINT32_C(0x10000) /* - * The resize_toggle bit tells that the CQ cutoff is done. - * Every time CQ is resized by CQ cutoff, this bit toggles when it - * is done. If this bit toggles, HW can restart to use the resized - * CQ. + * The toggle value is used in CQ_ARMENA, CQ_ARMSE, CQ_ARMALL, + * SRQ_ARMENA, SRQ_ARM, and CQ_CUTOFF_ACK doorbells to qualify the + * doorbell as valid. This value should be taken from the latest NQE + * or cutoff completion. + * + * Doorbells of the above types with the wrong toggle value will be + * ignored. This is how old values in of backup doorbells are + * ignored. */ - #define DBC_ABSOLUTE_DB_32_RESIZE_TOGGLE UINT32_C(0x20000) + #define DBC_ABSOLUTE_DB_32_TOGGLE_MASK UINT32_C(0x60000) + #define DBC_ABSOLUTE_DB_32_TOGGLE_SFT 17 /* * This value identifies the resource that the doorbell is intended * to notify. @@ -75556,18 +89136,18 @@ typedef struct dbc_absolute_db_32 { * value into the full xID value by looking up the base xID for this * particular function and adding the mxID value to that base value. */ - #define DBC_ABSOLUTE_DB_32_MXID_MASK UINT32_C(0xfc0000) - #define DBC_ABSOLUTE_DB_32_MXID_SFT 18 + #define DBC_ABSOLUTE_DB_32_MXID_MASK UINT32_C(0x1f80000) + #define DBC_ABSOLUTE_DB_32_MXID_SFT 19 /* * This value defines the intended doorbell path between RoCE and * L2. */ - #define DBC_ABSOLUTE_DB_32_PATH_MASK UINT32_C(0x3000000) - #define DBC_ABSOLUTE_DB_32_PATH_SFT 24 + #define DBC_ABSOLUTE_DB_32_PATH_MASK UINT32_C(0x6000000) + #define DBC_ABSOLUTE_DB_32_PATH_SFT 25 /* This is a RoCE doorbell message. */ - #define DBC_ABSOLUTE_DB_32_PATH_ROCE (UINT32_C(0x0) << 24) + #define DBC_ABSOLUTE_DB_32_PATH_ROCE (UINT32_C(0x0) << 25) /* This is a L2 doorbell message. */ - #define DBC_ABSOLUTE_DB_32_PATH_L2 (UINT32_C(0x1) << 24) + #define DBC_ABSOLUTE_DB_32_PATH_L2 (UINT32_C(0x1) << 25) #define DBC_ABSOLUTE_DB_32_PATH_LAST DBC_ABSOLUTE_DB_32_PATH_L2 /* * This indicates it is valid doorbell update. It should be set for @@ -75576,35 +89156,29 @@ typedef struct dbc_absolute_db_32 { * in the backup doorbell location at time zero to indicate that the * backup doorbell has not yet been written. */ - #define DBC_ABSOLUTE_DB_32_VALID UINT32_C(0x4000000) - /* - * When this bit is set to one, the chip will capture debug - * information for the doorbell ring. This is intended to only be - * used on SQ doorbell rings. - */ - #define DBC_ABSOLUTE_DB_32_DEBUG_TRACE UINT32_C(0x8000000) + #define DBC_ABSOLUTE_DB_32_VALID UINT32_C(0x8000000) /* This value identifies the type of doorbell being written. */ #define DBC_ABSOLUTE_DB_32_TYPE_MASK UINT32_C(0xf0000000) #define DBC_ABSOLUTE_DB_32_TYPE_SFT 28 /* - * This is a SQ producer index update. It indicates one or more + * This is a SQ producer index update. It indicates one or more * new entries have been written to the SQ for the QPID indicated * on the xID field. This type is valid for L2, RoCE and Engine * path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_SQ (UINT32_C(0x0) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_SQ (UINT32_C(0x0) << 28) /* - * This is a RQ producer index update. It indicates one or more + * This is a RQ producer index update. It indicates one or more * new entries have been written to the RQ for the QPID indicated * on the xID field. This type is valid for RoCE path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_RQ (UINT32_C(0x1) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_RQ (UINT32_C(0x1) << 28) /* - * This is a SRQ producer index update. It indicates one or more + * This is a SRQ producer index update. It indicates one or more * new entries have been written to the SRQ for the SID indicated * on the xID field. This type is valid for L2 and RoCE path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_SRQ (UINT32_C(0x2) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_SRQ (UINT32_C(0x2) << 28) /* * This doorbell command arms the SRQ async event. * The xID field must identify the SID that is begin armed. @@ -75614,11 +89188,11 @@ typedef struct dbc_absolute_db_32 { */ #define DBC_ABSOLUTE_DB_32_TYPE_SRQ_ARM (UINT32_C(0x3) << 28) /* - * This is a CQ consumer index update. It indicates one or more + * This is a CQ consumer index update. It indicates one or more * entries have been processed off the CQ indicated on the xID * field.This type is valid for L2, RoCE and Engine path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_CQ (UINT32_C(0x4) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_CQ (UINT32_C(0x4) << 28) /* * this is a CQ consumer index update that also arms the CQ for * solicited events. This type is valid for RoCE path. @@ -75629,13 +89203,34 @@ typedef struct dbc_absolute_db_32 { * for any new CQE. This type is valid for L2, RoCE and Engine * path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_CQ_ARMALL (UINT32_C(0x6) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_CQ_ARMALL (UINT32_C(0x6) << 28) + /* + * This is a CQ arm enable message. This message must be sent from + * the privileged driver before a new CQ_ARMSE or CQ_ARMALL message + * will be accepted from user space (non-privileged doorbell page). + * The index and epoch for this doorbell type are unused. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_ABSOLUTE_DB_32_TYPE_CQ_ARMENA (UINT32_C(0x7) << 28) + /* + * This doorbell command enables the SRQ async event to be armed. + * This message must be sent from the privileged driver before a + * new SRQ_ARM message will be accepted from user space. + * The xID field must identify the SID that is being enabled for + * arm. The index and epoch for this doorbell type are unused. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_ABSOLUTE_DB_32_TYPE_SRQ_ARMENA (UINT32_C(0x8) << 28) /* * This is a NQ consumer index update. It indicates one or more * entries have been processed off the NQ indicated on the xID * field. This type is valid for L2, RoCE and Engine path. */ - #define DBC_ABSOLUTE_DB_32_TYPE_NQ (UINT32_C(0xa) << 28) + #define DBC_ABSOLUTE_DB_32_TYPE_NQ (UINT32_C(0xa) << 28) /* * This is a NQ consumer index update that also arms the NQ for * any new NQE. This type is valid for L2, RoCE and Engine path. @@ -75707,20 +89302,20 @@ typedef struct dbc_relative_db_32 { #define DBC_RELATIVE_DB_32_TYPE_MASK UINT32_C(0xe0000000) #define DBC_RELATIVE_DB_32_TYPE_SFT 29 /* - * This is a SQ producer index update. It indicates one or more + * This is a SQ producer index update. It indicates one or more * new entries have been written to the SQ for the QPID indicated * on the xID field. This type is valid for L2, RoCE and Engine * path. */ #define DBC_RELATIVE_DB_32_TYPE_SQ (UINT32_C(0x0) << 29) /* - * This is a SRQ producer index update. It indicates one or more + * This is a SRQ producer index update. It indicates one or more * new entries have been written to the SRQ for the SID indicated * on the xID field. This type is valid for L2 and RoCE path. */ #define DBC_RELATIVE_DB_32_TYPE_SRQ (UINT32_C(0x1) << 29) /* - * This is a CQ consumer index update. It indicates one or more + * This is a CQ consumer index update. It indicates one or more * entries have been processed off the CQ indicated on the xID * field.This type is valid for L2, RoCE and Engine path. */ @@ -75759,7 +89354,7 @@ typedef struct dbc_relative_db_32 { /* dbc_drk (size:128b/16B) */ typedef struct dbc_drk { - uint32_t db_format_linked_last_valid; + uint32_t db_format_linked_last_valid_stride_size; /* * This indicates it is valid entry. It should be set for each * doorbell written to the chip. The bit should be cleared at time @@ -75785,11 +89380,55 @@ typedef struct dbc_drk { */ #define DBC_DRK_DB_FORMAT_B32A (UINT32_C(0x1) << 3) #define DBC_DRK_DB_FORMAT_LAST DBC_DRK_DB_FORMAT_B32A + /* + * This field controls the stride feature. The stride feature is + * more bandwidth efficient on the PCIE bus when only a small number + * of doorbells are used in each cache line. + */ + #define DBC_DRK_STRIDE_MASK UINT32_C(0x300) + #define DBC_DRK_STRIDE_SFT 8 + /* + * When stride is off, the DBR will read all the bytes in + * an application page until a NULL doorbell is found or + * the end of the 4K page is reached. + */ + #define DBC_DRK_STRIDE_OFF (UINT32_C(0x0) << 8) + /* + * When stride is 1, the DBR will read the 'size' doorbells, + * starting at the next 64B cache line boundary or until + * a NULL doorbell is found in the application page or + * the end of the 4K page is reached. + */ + #define DBC_DRK_STRIDE_SZ64 (UINT32_C(0x1) << 8) + /* + * When stride is 2, the DBR will read the 'size' doorbells, + * starting at the next 128B cache line boundary or until + * a NULL doorbell is found in the application page or + * the end of the 4K page is reached. + */ + #define DBC_DRK_STRIDE_SZ128 (UINT32_C(0x2) << 8) + #define DBC_DRK_STRIDE_LAST DBC_DRK_STRIDE_SZ128 + /* + * This value controls how many doorbells are read at each stride + * when stride mode is in use. + */ + #define DBC_DRK_SIZE_MASK UINT32_C(0xc00) + #define DBC_DRK_SIZE_SFT 10 + /* 4*8B is read at the start of each stride. */ + #define DBC_DRK_SIZE_FOUR (UINT32_C(0x0) << 10) + /* 1*8B is read at the start of each stride. */ + #define DBC_DRK_SIZE_ONE (UINT32_C(0x1) << 10) + /* 2*8B is read at the start of each stride. */ + #define DBC_DRK_SIZE_TWO (UINT32_C(0x2) << 10) + /* 3*8B is read at the start of each stride. */ + #define DBC_DRK_SIZE_THREE (UINT32_C(0x3) << 10) + #define DBC_DRK_SIZE_LAST DBC_DRK_SIZE_THREE uint32_t pi; /* * Page Index portion of DPI{VF_VALID,VFID,PI}. The pi needs to match - * the value from the context DPI for the operation to be valid or the - * pi must be zero, indicating a write from the privileged driver. + * the value from the context DPI for the operation to be valid or + * the pi must be zero, indicating a write from the privileged + * driver. * * pi in the kernel memory table is there for DBR to generate the DPI * message to the client. @@ -75807,6 +89446,420 @@ typedef struct dbc_drk { } dbc_drk_t, *pdbc_drk_t; /* + * The kernel memory structure is per-type (SQ, RQ, SRQ/SRQ_ARM and + * CQ/CQ_ARMSE/CQ_ARMALL). Each kernel driver will support a table for + * the doorbell recovery. + */ +/* dbc_drk64 (size:128b/16B) */ + +typedef struct dbc_drk64 { + uint64_t flags; + /* + * This indicates it is valid entry. It should be set for each + * doorbell written to the chip. The bit should be cleared at time + * zero to indicate that it has not yet been written. The bit i + * should be cleared when the function for the table is disabled. + */ + #define DBC_DRK64_VALID UINT32_C(0x1) + /* This indicates it is last entry for the table. */ + #define DBC_DRK64_LAST UINT32_C(0x2) + /* This indicates it is entry for the next 4KB kernel memory pointer. */ + #define DBC_DRK64_LINKED UINT32_C(0x4) + /* + * This field indicates if the doorbells in the table are 32b + * absolute or 64b format. + */ + #define DBC_DRK64_DB_FORMAT UINT32_C(0x8) + /* The doorbells are 64b format. */ + #define DBC_DRK64_DB_FORMAT_B64 (UINT32_C(0x0) << 3) + /* + * The doorbells are in the absolute 32b format. The doorbell + * is in the right-most half of the 64b space provided in the + * application table entry. + */ + #define DBC_DRK64_DB_FORMAT_B32A (UINT32_C(0x1) << 3) + #define DBC_DRK64_DB_FORMAT_LAST DBC_DRK64_DB_FORMAT_B32A + /* + * This field controls the stride feature. The stride feature is + * more bandwidth efficient on the PCIE bus when only a small number + * of doorbells are used in each cache line. + */ + #define DBC_DRK64_STRIDE_MASK UINT32_C(0x300) + #define DBC_DRK64_STRIDE_SFT 8 + /* + * When stride is off, the DBR will read all the bytes in + * an application page until a NULL doorbell is found or + * the end of the 4K page is reached. + */ + #define DBC_DRK64_STRIDE_OFF (UINT32_C(0x0) << 8) + /* + * When stride is 1, the DBR will read the 'size' doorbells, + * starting at the next 64B cache line boundary or until + * a NULL doorbell is found in the application page or + * the end of the 4K page is reached. + */ + #define DBC_DRK64_STRIDE_SZ64 (UINT32_C(0x1) << 8) + /* + * When stride is 2, the DBR will read the 'size' doorbells, + * starting at the next 128B cache line boundary or until + * a NULL doorbell is found in the application page or + * the end of the 4K page is reached. + */ + #define DBC_DRK64_STRIDE_SZ128 (UINT32_C(0x2) << 8) + #define DBC_DRK64_STRIDE_LAST DBC_DRK64_STRIDE_SZ128 + /* + * This value controls how many doorbells are read at each stride + * when stride mode is in use. + */ + #define DBC_DRK64_SIZE_MASK UINT32_C(0xc00) + #define DBC_DRK64_SIZE_SFT 10 + /* 4*8B is read at the start of each stride. */ + #define DBC_DRK64_SIZE_FOUR (UINT32_C(0x0) << 10) + /* 1*8B is read at the start of each stride. */ + #define DBC_DRK64_SIZE_ONE (UINT32_C(0x1) << 10) + /* 2*8B is read at the start of each stride. */ + #define DBC_DRK64_SIZE_TWO (UINT32_C(0x2) << 10) + /* 3*8B is read at the start of each stride. */ + #define DBC_DRK64_SIZE_THREE (UINT32_C(0x3) << 10) + #define DBC_DRK64_SIZE_LAST DBC_DRK64_SIZE_THREE + /* + * Page Index portion of DPI{VF_VALID,VFID,PI}. The pi needs to match + * the value from the context DPI for the operation to be valid or + * the pi must be zero, indicating a write from the privileged + * driver. + * + * pi in the kernel memory table is there for DBR to generate the DPI + * message to the client. + */ + #define DBC_DRK64_PI_MASK UINT32_C(0xffff00000000)L + #define DBC_DRK64_PI_SFT 32 + /* + * It is the application memory page(4KB) pointer when linked = 0. + * It is the next kernel memory page(4KB) pointer when linked = 1. + * The pointer doesn't have to be aligned to the page(4KB) but it + * should be aligned to 128B boundary. This means that the bottom + * 7b of the pointer must be zero. + */ + uint64_t memptr; +} dbc_drk64_t, *pdbc_drk64_t; + +/* + * This is the 64b doorbell format. The host writes this message + * format directly to byte offset 0 of the appropriate doorbell page. + */ +/* dbc_dbc_v3 (size:64b/8B) */ + +typedef struct dbc_dbc_v3 { + uint32_t index; + /* + * This value is the index being written. + * + * For SQ/RQ/SRQ, this is the producer index. It should be set to + * the queue index of the last WQE/BD written plus the number of + * index units in the WQE/BD. For example, if the number of index + * units in an SQ WQE is 8 and the WQE was written to the first + * location in the queue (zero), this index should be written to 8. + * The index should point to the start of the first location that + * has not been filled in with WQE/BD data. For SQ (both RoCE and + * L2), the index unit is 16B. For RQ/SRQ, the index unit is 1 WQE + * (RoCE) or 1 BD (L2). + * + * For CQ, this is the consumer index and should be the starting + * queue index of the last CQE processed plus the size of the last + * processed CQE in index units. The index should point to the + * start of the first CQE in the queue that has not been processed. + * The index unit is 16B. + * + * For NQ, this is the consumer index and should be the starting + * queue index of the last NQE processed plus the size of the last + * processed NQE in index units. The index should point to the + * start of the first NQE in the queue that has not been processed. + * The index unit is 16B. + */ + #define DBC_DBC_V3_INDEX_MASK UINT32_C(0xffffff) + #define DBC_DBC_V3_INDEX_SFT 0 + /* + * The epoch bit provides a frame of reference for the queue index. + * S/W will toggle this bit in the doorbell each time index range is + * wrapped. This allows the receiving HW block to more efficiently + * detect out-of-order doorbells and to ignore the older doorbells. + * Out-of-order doorbells occur normally during dropped doorbell + * recovery. + */ + #define DBC_DBC_V3_EPOCH UINT32_C(0x1000000) + /* + * The toggle value is used in CQ_ARMENA, CQ_ARMSE, CQ_ARMALL, + * SRQ_ARMENA, SRQ_ARM, and CQ_CUTOFF_ACK doorbells to qualify the + * doorbell as valid. This value should be taken from the latest + * NQE or cutoff completion. + * + * Doorbells of the above types with the wrong toggle value will + * be ignored. This is how old values in of backup doorbells + * are ignored. + */ + #define DBC_DBC_V3_TOGGLE_MASK UINT32_C(0x6000000) + #define DBC_DBC_V3_TOGGLE_SFT 25 + uint32_t type_path_xid; + /* + * This value identifies the resource that the doorbell is intended + * to notify. + * + * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For + * CQ, this is the CID. For NQ, this is the NID. + * + * Unused bits (for example bits [11:7] of the SID value) must be + * zero. + */ + #define DBC_DBC_V3_XID_MASK UINT32_C(0xfff) + #define DBC_DBC_V3_XID_SFT 0 + /* + * This value defines the intended doorbell path between RoCE and + * L2. + */ + #define DBC_DBC_V3_PATH_MASK UINT32_C(0x3000000) + #define DBC_DBC_V3_PATH_SFT 24 + /* This is a RoCE doorbell message. */ + #define DBC_DBC_V3_PATH_ROCE (UINT32_C(0x0) << 24) + /* This is a L2 doorbell message. */ + #define DBC_DBC_V3_PATH_L2 (UINT32_C(0x1) << 24) + #define DBC_DBC_V3_PATH_LAST DBC_DBC_V3_PATH_L2 + /* + * This indicates it is valid doorbell update. It should be set for + * each doorbell written to the chip and set when doorbell message is + * written to the backup doorbell location. The bit should be cleared + * in the backup doorbell location at time zero to indicate that the + * backup doorbell has not yet been written. + */ + #define DBC_DBC_V3_VALID UINT32_C(0x4000000) + /* + * When this bit is set to one, the chip will capture debug + * information for the doorbell ring. This is intended to only be + * used on SQ doorbell rings. + */ + #define DBC_DBC_V3_DEBUG_TRACE UINT32_C(0x8000000) + /* This value identifies the type of doorbell being written. */ + #define DBC_DBC_V3_TYPE_MASK UINT32_C(0xf0000000) + #define DBC_DBC_V3_TYPE_SFT 28 + /* + * This is a SQ producer index update. It indicates one or more + * new entries have been written to the SQ for the QPID indicated + * on the xID field. This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_SQ (UINT32_C(0x0) << 28) + /* + * This is a RQ producer index update. It indicates one or more + * new entries have been written to the RQ for the QPID indicated + * on the xID field. This type is valid for RoCE path. + */ + #define DBC_DBC_V3_TYPE_RQ (UINT32_C(0x1) << 28) + /* + * This is a SRQ producer index update. It indicates one or more + * new entries have been written to the SRQ for the SID indicated + * on the xID field. This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_SRQ (UINT32_C(0x2) << 28) + /* + * This doorbell command arms the SRQ async event. The xID field + * must identify the SID that is begin armed. The index field is + * will set the arm threshold such that a notification will be + * generated if less than that number or SRQ entries are posted. + * + * This type is valid for RoCE path. + */ + #define DBC_DBC_V3_TYPE_SRQ_ARM (UINT32_C(0x3) << 28) + /* + * CQ doorbell is used to update the consumer index for the CQ + * for overflow detection. It should only be sent if overflow + * detection is enabled for the CQ. Keep in mind that if + * doorbells are being dropped due to PCIE ordering rules, you + * may get a false overflow detection if you are checking for CQ + * overflow. + * + * This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_CQ (UINT32_C(0x4) << 28) + /* + * This is a CQ consumer index update that also arms the CQ for + * solicited events. This is for roce only not for l2. + * + * The index is used as the location of the last CQE that was + * processed by the driver. The new interrupt will be generated + * based on this location. + * + * This type is valid for RoCE path. + */ + #define DBC_DBC_V3_TYPE_CQ_ARMSE (UINT32_C(0x5) << 28) + /* + * This is a CQ consumer index update that also arms the CQ for + * any new CQE. + * + * The index is used as the location of the last CQE that was + * processed by the driver. The new interrupt will be generated + * based on this location. + * + * This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_CQ_ARMALL (UINT32_C(0x6) << 28) + /* + * This is a CQ arm enable message. This message must be sent + * from the privileged driver before a new CQ_ARMSE or CQ_ARMALL + * message will be accepted from user space (non-privileged + * doorbell page). The index and epoch for this doorbell type are + * unused. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_DBC_V3_TYPE_CQ_ARMENA (UINT32_C(0x7) << 28) + /* + * This doorbell command enables the SRQ async event to be armed. + * This message must be sent from the privileged driver before + * a new SRQ_ARM message will be accepted from user space. The + * xID field must identify the SID that is being enabled for arm. + * The index and epoch for this doorbell type are unused. + * + * This doorbell can only be sent from the privileged (first) + * doorbell page of a function. + */ + #define DBC_DBC_V3_TYPE_SRQ_ARMENA (UINT32_C(0x8) << 28) + /* + * This doorbell type is used to acknowledge a cutoff completion + * in the CQ. The index and epoch for this doorbell type are + * unused. This doorbell is sent when the cutoff completion has + * been processed and the old CQ in a CQ resize operation is no + * longer needed. + * + * The index and epoch must be valid for this doorbell if + * overflow checking is enabled for the CQ. + */ + #define DBC_DBC_V3_TYPE_CQ_CUTOFF_ACK (UINT32_C(0x9) << 28) + /* + * This is a NQ consumer index update. It indicates one or more + * entries have been processed off the NQ indicated on the xID + * field. It will also mask the NQ for any new NQE. This type is + * valid for L2 and RoCE path. + * + * Thor is broken in that it doesn't mask a legacy INTA interrupt + * when used at the start of an ISR, as it is supposed to be. + * + * type=NQ masks the current interrupt. When the iSR starts, it + * writes a type=NQ with the current consumer index. For legacy + * PCI interrupts, this needs to mask the interrupt so the legacy + * interrupt is deasserted. Then the driver does some work and + * writes some more type=NQ. Finally the driver stops the ISR and + * does a type=NQ_ARM to get another interrupt (when needed). The + * only reason to use type=NQ_MASK is to back out of the armed + * state. In that request, the index update is not required. + */ + #define DBC_DBC_V3_TYPE_NQ (UINT32_C(0xa) << 28) + /* + * This is a NQ consumer index update that also arms the NQ for + * any new NQE. + * + * This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_NQ_ARM (UINT32_C(0xb) << 28) + /* + * This doorbell will assign a new NQ to a CQ. This is handy if + * the user wants to change which interrupt handler is going to + * process a particular CQ. This doorbell must be sent from the + * privileged driver. + * + * The xID must be the CID for the CQ that needs to be changed. + * The index value is the NQID of the new NQ that will be used + * for future notifications. epoch and toggle are ignored for + * this doorbell type. + * + * The CQ will disarm notifications and generate a NQE to the old + * NQ with the nq_reassign type value. The chip will guarantee + * that no notification will be sent to the old NQ after the + * nq_reassign NQE has been sent. + * + * This type is valid for L2 and RoCE CQs. + */ + #define DBC_DBC_V3_TYPE_CQ_REASSIGN (UINT32_C(0xc) << 28) + /* + * This masks the NQ for any new NQE. This will NOT update the NQ + * consumer index. + * + * This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_NQ_MASK (UINT32_C(0xe) << 28) + /* + * All other fields should be zero for NULL doorbell. + * + * For doorbell recovery, NULL doorbell type in the Application + * table indicates that it is the last QP entry for the function. + * This type is valid for L2 and RoCE path. + */ + #define DBC_DBC_V3_TYPE_NULL (UINT32_C(0xf) << 28) + #define DBC_DBC_V3_TYPE_LAST DBC_DBC_V3_TYPE_NULL +} dbc_dbc_v3_t, *pdbc_dbc_v3_t; + +/* + * This is the RoCE Express Doorbell format. The host writes this + * message format directly to offset 0x40 of the appropriate doorbell + * page. Express doorbells are used when the chip will be owning the + * SQ, RQ, and SRQ as well as the producer indexes for each queue. This + * provides a simple fastpath programming model. + * + * Express doorbell must be received by the chip as a single TLP + * message. + */ +/* dbc_xp (size:512b/64B) */ + +typedef struct dbc_xp { + uint32_t reserved; + uint32_t type_xid; + /* + * This value identifies the resource that the doorbell is intended + * to notify. + * + * For SQ and RQ, this is the QPID. For SRQ, this is the SID. For + * CQ, this is the CID. For NQ, this is the NID. + * + * Unused bits (for example bits [11:7] of the SID value) must be + * zero. + */ + #define DBC_XP_XID_MASK UINT32_C(0xfff) + #define DBC_XP_XID_SFT 0 + /* + * When this bit is set to one, the chip will capture debug + * information for the doorbell ring. This is intended to only be + * used on SQ doorbell rings. + */ + #define DBC_XP_DEBUG_TRACE UINT32_C(0x1000000) + /* This value identifies the type of doorbell being written. */ + #define DBC_XP_TYPE_MASK UINT32_C(0xf0000000) + #define DBC_XP_TYPE_SFT 28 + /* + * This is a SQ producer index update. It indicates one or more + * new entries have been written to the SQ for the QPID indicated + * on the xID field. This type is valid for L2, RoCE and Engine + * path. + */ + #define DBC_XP_TYPE_SQ (UINT32_C(0x0) << 28) + /* + * This is a RQ producer index update. It indicates one or more + * new entries have been written to the RQ for the QPID indicated + * on the xID field. This type is valid for RoCE path. + */ + #define DBC_XP_TYPE_RQ (UINT32_C(0x1) << 28) + /* + * This is a SRQ producer index update. It indicates one or more + * new entries have been written to the SRQ for the SID indicated + * on the xID field. This type is valid for L2 and RoCE path. + */ + #define DBC_XP_TYPE_SRQ (UINT32_C(0x2) << 28) + #define DBC_XP_TYPE_LAST DBC_XP_TYPE_SRQ + /* + * This field hold one express WQE. The WQE must be appropriate for + * the queue selected by the type field. + */ + uint32_t wqe[14]; +} dbc_xp_t, *pdbc_xp_t; + +/* * This is a firmware status register that indicates the software status * exposed by the firmware to the host. * @@ -75820,9 +89873,10 @@ typedef struct fw_status_reg { * These bits indicate the status as being reported by the firmware. * * The value should be interpreted as follows: - * A value below 0x8000 is an indication that the firmware is still in the - * process of starting up and is not ready. The host driver should - * continue waiting with a timeout for firmware status to be ready. + * A value below 0x8000 is an indication that the firmware is still + * in the process of starting up and is not ready. The host driver + * should continue waiting with a timeout for firmware status to be + * ready. * > 0x0000 to 0x00FF : SBL state information * > 0x0200 to 0x02FF : SBI state information * > 0x0400 to 0x04FF : SRT state information @@ -75830,14 +89884,15 @@ typedef struct fw_status_reg { * > 0x0800 to 0x08FF : External Firmware state information * > 0x0A00 to 0x0FFF : Reserved for future fw functionality * - * A value of 0x8000 indicates firmware is ready and healthy. The host - * driver can start initiating HWRM commands to the firmware. + * A value of 0x8000 indicates firmware is ready and healthy. The + * host driver can start initiating HWRM commands to the firmware. * - * A value over 0x8000 is an indication that the firmware has detected - * a fatal error, this error could be in one of the hardware block or - * in a software module. The lower 8 bits indicate a block/module - * specific error and the upper 8 bits identify the hardware block - * or firmware module that was the source of the error. + * A value over 0x8000 is an indication that the firmware has + * detected a fatal error, this error could be in one of the hardware + * block or in a software module. The lower 8 bits indicate a + * block/module specific error and the upper 8 bits identify the + * hardware block or firmware module that was the source of the + * error. * > 0x81XX - 0xBFXX : 63 ASIC blocks * > 0xC0XX to 0xFDXX : 62 Firmware modules * > 0xFE00 to 0xFEFF : External firmware module @@ -75863,10 +89918,10 @@ typedef struct fw_status_reg { * recoverable with a full reset. * * This bit should be used by host software and deployment models - * that support error recovery by resetting the controller. A recovery - * should be attempted from a fatal error condition only if this bit - * is set. This bit is meaningful only when the code field is greater - * than 0x8000 (32768 decimal). + * that support error recovery by resetting the controller. A + * recovery should be attempted from a fatal error condition only if + * this bit is set. This bit is meaningful only when the code field + * is greater than 0x8000 (32768 decimal). */ #define FW_STATUS_REG_RECOVERABLE UINT32_C(0x20000) /* @@ -75874,51 +89929,52 @@ typedef struct fw_status_reg { * currently recording a crash dump. * * This bit provides a hint to the host driver if the firmware is - * currently recording a crash dump. Host driers should avoid resetting - * the controller when a crash dump is in progress if possible. This - * bit is meaningful only when the code field is greater than - * 0x8000 (32768 decimal). + * currently recording a crash dump. Host driers should avoid + * resetting the controller when a crash dump is in progress if + * possible. This bit is meaningful only when the code field is + * greater than 0x8000 (32768 decimal). */ #define FW_STATUS_REG_CRASHDUMP_ONGOING UINT32_C(0x40000) /* - * Crash dump is available. If set indicates that a firmware crash dump - * was recorded before and is now available. + * Crash dump is available. If set indicates that a firmware crash + * dump was recorded before and is now available. * - * This bit provides indication to the host driver that the firmware has - * completed a crash dump. This bit is meaningful only when the code - * field is greater than 0x8000 (32768 decimal). + * This bit provides indication to the host driver that the firmware + * has completed a crash dump. This bit is meaningful only when the + * code field is greater than 0x8000 (32768 decimal). */ #define FW_STATUS_REG_CRASHDUMP_COMPLETE UINT32_C(0x80000) /* - * This bit is used to indicate device state when it enters the shutdown mode - * and stopped the communication with the host. The host should initiate the - * reload of firmware image or initiate the reset to bring the device to the - * normal operational state and re-establish the communication. + * This bit is used to indicate device state when it enters the + * shutdown mode and stopped the communication with the host. The + * host should initiate the reload of firmware image or initiate the + * reset to bring the device to the normal operational state and + * re-establish the communication. * - * This bit is meaningful only when the code field is greater than 0x8000 - * (32768 decimal). + * This bit is meaningful only when the code field is greater than + * 0x8000 (32768 decimal). */ #define FW_STATUS_REG_SHUTDOWN UINT32_C(0x100000) /* * This bit will be set to 1 by the FW when FW crashed without master * function. * - * This bit is controller specific, not all products will support this bit. - * This bit is valid only when the code field is greater than 0x8000 - * (32768 decimal). + * This bit is controller specific, not all products will support + * this bit. This bit is valid only when the code field is greater + * than 0x8000 (32768 decimal). */ #define FW_STATUS_REG_CRASHED_NO_MASTER UINT32_C(0x200000) /* - * The firmware sets this bit to 1 when the firmware has taken an exception - * and expects to initiate error recovery. + * The firmware sets this bit to 1 when the firmware has taken an + * exception and expects to initiate error recovery. * * This bit is valid only when the code field is greater than 0x8000 * (32768 decimal). */ #define FW_STATUS_REG_RECOVERING UINT32_C(0x400000) /* - * The SBL sets this bit to indicate whether manu_debug pin is detected high - * or low. + * The SBL sets this bit to indicate whether manu_debug pin is + * detected high or low. */ #define FW_STATUS_REG_MANU_DEBUG_STATUS UINT32_C(0x800000) } fw_status_reg_t, *pfw_status_reg_t; @@ -76037,9 +90093,9 @@ typedef struct hwrm_selftest_qlist_output { #define HWRM_SELFTEST_QLIST_OUTPUT_AVAILABLE_TESTS_REGISTER_TEST UINT32_C(0x4) /* Can run the memory test. */ #define HWRM_SELFTEST_QLIST_OUTPUT_AVAILABLE_TESTS_MEMORY_TEST UINT32_C(0x8) - /* Can run the PCIe serdes test. */ + /* Can run the PCIe serdes test. (deprecated) */ #define HWRM_SELFTEST_QLIST_OUTPUT_AVAILABLE_TESTS_PCIE_SERDES_TEST UINT32_C(0x10) - /* Can run the Ethernet serdes test. */ + /* Can run the Ethernet serdes test. (deprecated) */ #define HWRM_SELFTEST_QLIST_OUTPUT_AVAILABLE_TESTS_ETHERNET_SERDES_TEST UINT32_C(0x20) uint8_t offline_tests; /* The NVM test is an offline test. */ @@ -76050,9 +90106,9 @@ typedef struct hwrm_selftest_qlist_output { #define HWRM_SELFTEST_QLIST_OUTPUT_OFFLINE_TESTS_REGISTER_TEST UINT32_C(0x4) /* The memory test is an offline test. */ #define HWRM_SELFTEST_QLIST_OUTPUT_OFFLINE_TESTS_MEMORY_TEST UINT32_C(0x8) - /* The PCIe serdes test is an offline test. */ + /* The PCIe serdes test is an offline test. (deprecated) */ #define HWRM_SELFTEST_QLIST_OUTPUT_OFFLINE_TESTS_PCIE_SERDES_TEST UINT32_C(0x10) - /* The Ethernet serdes test is an offline test. */ + /* The Ethernet serdes test is an offline test. (deprecated) */ #define HWRM_SELFTEST_QLIST_OUTPUT_OFFLINE_TESTS_ETHERNET_SERDES_TEST UINT32_C(0x20) uint8_t unused_0; /* @@ -76062,48 +90118,14 @@ typedef struct hwrm_selftest_qlist_output { uint16_t test_timeout; uint8_t unused_1[2]; /* - * This field represents the name of the NVM test (ASCII chars - * with NULL at the end). - */ - char test0_name[32]; - /* - * This field represents the name of the link test (ASCII chars - * with NULL at the end). - */ - char test1_name[32]; - /* - * This field represents the name of the register test (ASCII chars - * with NULL at the end). - */ - char test2_name[32]; - /* - * This field represents the name of the memory test (ASCII chars + * This field represents array of 8 test name strings (ASCII chars * with NULL at the end). */ - char test3_name[32]; - /* - * This field represents the name of the PCIe serdes test (ASCII chars - * with NULL at the end). - */ - char test4_name[32]; - /* - * This field represents the name of the Ethernet serdes test (ASCII chars - * with NULL at the end). - */ - char test5_name[32]; - /* - * This field represents the name of some future test (ASCII chars - * with NULL at the end). - */ - char test6_name[32]; - /* - * This field represents the name of some future test (ASCII chars - * with NULL at the end). - */ - char test7_name[32]; + char test_name[8][32]; /* * The lowest available target BER that is supported by FW eyescope. - * A Value of 3 indicates that FW supports 1e-8, 1e-9, 1e-10, and 1e-11. + * A Value of 3 indicates that FW supports 1e-8, 1e-9, 1e-10, and + * 1e-11. (deprecated) */ uint8_t eyescope_target_BER_support; /* Eyescope supports a target BER of 1e-8 */ @@ -76120,9 +90142,9 @@ typedef struct hwrm_selftest_qlist_output { uint8_t unused_2[6]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76174,9 +90196,9 @@ typedef struct hwrm_selftest_exec_input { #define HWRM_SELFTEST_EXEC_INPUT_FLAGS_REGISTER_TEST UINT32_C(0x4) /* Run the memory test. */ #define HWRM_SELFTEST_EXEC_INPUT_FLAGS_MEMORY_TEST UINT32_C(0x8) - /* Run the PCIe serdes test. */ + /* Run the PCIe serdes test. (deprecated) */ #define HWRM_SELFTEST_EXEC_INPUT_FLAGS_PCIE_SERDES_TEST UINT32_C(0x10) - /* Run the Ethernet serdes test. */ + /* Run the Ethernet serdes test. (deprecated) */ #define HWRM_SELFTEST_EXEC_INPUT_FLAGS_ETHERNET_SERDES_TEST UINT32_C(0x20) uint8_t unused_0[7]; } hwrm_selftest_exec_input_t, *phwrm_selftest_exec_input_t; @@ -76202,33 +90224,52 @@ typedef struct hwrm_selftest_exec_output { #define HWRM_SELFTEST_EXEC_OUTPUT_REQUESTED_TESTS_REGISTER_TEST UINT32_C(0x4) /* A request was made to run the memory test. */ #define HWRM_SELFTEST_EXEC_OUTPUT_REQUESTED_TESTS_MEMORY_TEST UINT32_C(0x8) - /* A request was made to run the PCIe serdes test. */ + /* A request was made to run the PCIe serdes test. (deprecated) */ #define HWRM_SELFTEST_EXEC_OUTPUT_REQUESTED_TESTS_PCIE_SERDES_TEST UINT32_C(0x10) - /* A request was made to run the Ethernet serdes test. */ + /* A request was made to run the Ethernet serdes test. (deprecated) */ #define HWRM_SELFTEST_EXEC_OUTPUT_REQUESTED_TESTS_ETHERNET_SERDES_TEST UINT32_C(0x20) /* - * If a test was requested to be run as seen in the requested_tests field, - * this bit indicates whether the test was successful(1) or failed(0). + * If a test was requested to be run as seen in the requested_tests + * field, this bit indicates whether the test was successful(1) or + * failed(0). */ uint8_t test_success; - /* If requested, a value of 1 indicates the NVM test completed successfully. */ + /* + * If requested, a value of 1 indicates the NVM test completed + * successfully. + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_NVM_TEST UINT32_C(0x1) - /* If requested, a value of 1 indicates the link test completed successfully. */ + /* + * If requested, a value of 1 indicates the link test completed + * successfully. + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_LINK_TEST UINT32_C(0x2) - /* If requested, a value of 1 indicates the register test completed successfully. */ + /* + * If requested, a value of 1 indicates the register test completed + * successfully. + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_REGISTER_TEST UINT32_C(0x4) - /* If requested, a value of 1 indicates the memory test completed successfully. */ + /* + * If requested, a value of 1 indicates the memory test completed + * successfully. + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_MEMORY_TEST UINT32_C(0x8) - /* If requested, a value of 1 indicates the PCIe serdes test completed successfully. */ + /* + * If requested, a value of 1 indicates the PCIe serdes test + * completed successfully. (deprecated) + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_PCIE_SERDES_TEST UINT32_C(0x10) - /* If requested, a value of 1 indicates the Ethernet serdes test completed successfully. */ + /* + * If requested, a value of 1 indicates the Ethernet serdes test + * completed successfully. (deprecated) + */ #define HWRM_SELFTEST_EXEC_OUTPUT_TEST_SUCCESS_ETHERNET_SERDES_TEST UINT32_C(0x20) uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76286,9 +90327,9 @@ typedef struct hwrm_selftest_irq_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76340,12 +90381,13 @@ typedef struct hwrm_selftest_retrieve_serdes_data_input { uint32_t resp_data_offset; /* * Size of the buffer pointed to by resp_data_addr. The firmware may - * use this entire buffer or less than the entire buffer, but never more. + * use this entire buffer or less than the entire buffer, but never + * more. */ uint16_t data_len; /* - * This field allows this command to request the individual serdes tests - * to be run using this command. + * This field allows this command to request the individual serdes + * tests to be run using this command. */ uint8_t flags; /* Unused. */ @@ -76360,7 +90402,8 @@ typedef struct hwrm_selftest_retrieve_serdes_data_input { uint8_t options; /* * This field represents the PCIE lane number on which tools wants to - * retrieve eye plot. This field is valid only when ‘pcie_serdes_test’ flag is set. + * retrieve eye plot. This field is valid only when 'pcie_serdes_test' + * flag is set. * Valid values from 0 to 16. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_OPTIONS_PCIE_LANE_NO_MASK UINT32_C(0xf) @@ -76380,8 +90423,9 @@ typedef struct hwrm_selftest_retrieve_serdes_data_input { */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_OPTIONS_PROJ_TYPE_LEFT_TOP (UINT32_C(0x0) << 5) /* - * Value 1 indicates right/bottom projection in horizontal/vertical - * This value is valid only when eye_projection flag was set. + * Value 1 indicates right/bottom projection in + * horizontal/vertical. This value is valid only when + * eye_projection flag was set. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_OPTIONS_PROJ_TYPE_RIGHT_BOTTOM (UINT32_C(0x1) << 5) #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_OPTIONS_PROJ_TYPE_LAST HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_OPTIONS_PROJ_TYPE_RIGHT_BOTTOM @@ -76411,20 +90455,24 @@ typedef struct hwrm_selftest_retrieve_serdes_data_input { uint8_t action; /* * Value 0 indicates that collection of the eyescope should be - * returned synchronously in the output. This only applies to + * returned synchronously in the output. This only applies to * a targetBER of 1e-8. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_SYNCHRONOUS UINT32_C(0x0) - /* Value 1 indicates to the firmware to start the collection of the eyescope. */ + /* + * Value 1 indicates to the firmware to start the collection of the + * eyescope. + */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_START UINT32_C(0x1) /* - * Value 2 indicates to the firmware to respond with a progress percentage - * of the current eyescope collection from 0.0 to 100.0. + * Value 2 indicates to the firmware to respond with a progress + * percentage of the current eyescope collection from 0.0 to 100.0. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_PROGRESS UINT32_C(0x2) /* - * Value 3 indicates to stop the eyescope. if the progress percentage - * is 100.0, the data will be DMAed back to resp_data_addr. + * Value 3 indicates to stop the eyescope. if the progress + * percentage is 100.0, the data will be DMAed back to + * resp_data_addr. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_STOP UINT32_C(0x3) #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_LAST HWRM_SELFTEST_RETRIEVE_SERDES_DATA_INPUT_ACTION_STOP @@ -76453,16 +90501,17 @@ typedef struct hwrm_selftest_retrieve_serdes_data_output { */ uint16_t copied_data_len; /* - * Percentage of completion of collection of BER values from the current - * eyescope operation in tenths of a percentage. 0 (0.0) to 1000 (100.0) + * Percentage of completion of collection of BER values from the + * current eyescope operation in tenths of a percentage. 0 (0.0) to + * 1000 (100.0). */ uint16_t progress_percent; /* Timeout in seconds for timeout of an individual BER point. */ uint16_t timeout; uint8_t flags; /* - * This value indicates the structure of data returned by the firmware - * when DMA'ed to resp_data_addr + * This value indicates the structure of data returned by the + * firmware when DMA'ed to resp_data_addr. */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_OUTPUT_FLAGS_BIT_COUNT_TYPE UINT32_C(0x1) /* @@ -76472,7 +90521,7 @@ typedef struct hwrm_selftest_retrieve_serdes_data_output { #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_OUTPUT_FLAGS_BIT_COUNT_TYPE_BIT_COUNT_TOTAL UINT32_C(0x0) /* * Value 1 indicates that bit count is a power of - * 2 that bit_count is normalized to. A Value of 42 indicates + * 2 that bit_count is normalized to. A Value of 42 indicates * that BER = error_count / 2^42 */ #define HWRM_SELFTEST_RETRIEVE_SERDES_DATA_OUTPUT_FLAGS_BIT_COUNT_TYPE_BIT_COUNT_POW2 UINT32_C(0x1) @@ -76483,15 +90532,16 @@ typedef struct hwrm_selftest_retrieve_serdes_data_output { uint8_t unused_0; /* * Size of header prepended to the bit_count and error_count array. - * Use this value to skip forward to the bit_count and error_count array. + * Use this value to skip forward to the bit_count and error_count + * array. */ uint16_t hdr_size; uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76555,9 +90605,9 @@ typedef struct hwrm_mfg_fru_write_control_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76634,9 +90684,9 @@ typedef struct hwrm_mfg_timers_query_output { uint8_t unused_0[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76683,7 +90733,7 @@ typedef struct hwrm_mfg_otp_cfg_input { * This bit must be '1' for the crid field to be * configured. */ - #define HWRM_MFG_OTP_CFG_INPUT_ENABLES_CRID UINT32_C(0x1) + #define HWRM_MFG_OTP_CFG_INPUT_ENABLES_CRID UINT32_C(0x1) /* * This bit must be '1' for the srt_rev_id field to be * configured. @@ -76699,6 +90749,11 @@ typedef struct hwrm_mfg_otp_cfg_input { * configured. */ #define HWRM_MFG_OTP_CFG_INPUT_ENABLES_SBI_REV_ID UINT32_C(0x8) + /* + * This bit must be '1' for the max_speed field to be + * configured. + */ + #define HWRM_MFG_OTP_CFG_INPUT_ENABLES_MAX_SPEED_SELECT UINT32_C(0x10) /* This field indicates the crid value to be set. */ uint16_t crid_cfg_value; /* This field indicates the srt rev id value to be set. */ @@ -76707,7 +90762,18 @@ typedef struct hwrm_mfg_otp_cfg_input { uint16_t crt_rev_id_cfg_value; /* This field indicates the sbi rev id value to be set. */ uint16_t sbi_rev_id_cfg_value; - uint8_t unused_0[6]; + /* This field indicates the max speed value to be set. */ + uint16_t max_speed_cfg_value; + /* max speed value not configured. */ + #define HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_NOT_CONFIGURED UINT32_C(0x0) + /* max speed value 50G. */ + #define HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_50G UINT32_C(0x1) + /* max speed value 100G. */ + #define HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_100G UINT32_C(0x2) + /* max speed value 200G. */ + #define HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_200G UINT32_C(0x3) + #define HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_LAST HWRM_MFG_OTP_CFG_INPUT_MAX_SPEED_CFG_VALUE_200G + uint8_t unused_0[4]; } hwrm_mfg_otp_cfg_input_t, *phwrm_mfg_otp_cfg_input_t; /* hwrm_mfg_otp_cfg_output (size:128b/16B) */ @@ -76724,9 +90790,9 @@ typedef struct hwrm_mfg_otp_cfg_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76773,7 +90839,7 @@ typedef struct hwrm_mfg_otp_qcfg_input { * This bit must be '1' for the crid field to be * queried. */ - #define HWRM_MFG_OTP_QCFG_INPUT_ENABLES_CRID UINT32_C(0x1) + #define HWRM_MFG_OTP_QCFG_INPUT_ENABLES_CRID UINT32_C(0x1) /* * This bit must be '1' for the srt_rev_id field to be * queried. @@ -76789,10 +90855,15 @@ typedef struct hwrm_mfg_otp_qcfg_input { * queried. */ #define HWRM_MFG_OTP_QCFG_INPUT_ENABLES_SBI_REV_ID UINT32_C(0x8) + /* + * This bit must be '1' for the max_speed field to be + * queried. + */ + #define HWRM_MFG_OTP_QCFG_INPUT_ENABLES_MAX_SPEED_SELECT UINT32_C(0x10) uint8_t unused_0[6]; } hwrm_mfg_otp_qcfg_input_t, *phwrm_mfg_otp_qcfg_input_t; -/* hwrm_mfg_otp_qcfg_output (size:192b/24B) */ +/* hwrm_mfg_otp_qcfg_output (size:256b/32B) */ typedef struct hwrm_mfg_otp_qcfg_output { /* The specific error status for the command. */ @@ -76816,12 +90887,29 @@ typedef struct hwrm_mfg_otp_qcfg_output { uint16_t crt_rev_id; /* This field indicates the current sbi rev id value. */ uint16_t sbi_rev_id; - uint8_t unused_0[3]; + /* This field indicates the current max speed value. */ + uint16_t max_speed; + /* max speed value not configured. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_NOT_CONFIGURED UINT32_C(0x0) + /* max speed value 50G. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_50G UINT32_C(0x1) + /* max speed value 100G. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_100G UINT32_C(0x2) + /* max speed value 200G. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_200G UINT32_C(0x3) + #define HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_LAST HWRM_MFG_OTP_QCFG_OUTPUT_MAX_SPEED_200G + /* This field sets a bitmap for new enabled fields. */ + uint16_t enables_bitmap; + /* This bit checks max speed cfg enable. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_ENABLES_BITMAP_MAX_SPEED UINT32_C(0x10) + /* This bit validates this enable bitmap. */ + #define HWRM_MFG_OTP_QCFG_OUTPUT_ENABLES_BITMAP_ENABLES_VALID UINT32_C(0x8000) + uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76903,9 +90991,9 @@ typedef struct hwrm_mfg_hdma_test_output { uint8_t unused_0[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -76979,9 +91067,9 @@ typedef struct hwrm_mfg_fru_eeprom_write_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -77059,9 +91147,9 @@ typedef struct hwrm_mfg_fru_eeprom_read_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -77184,7 +91272,7 @@ typedef struct hwrm_mfg_soc_image_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77280,7 +91368,7 @@ typedef struct hwrm_mfg_soc_qstatus_output { uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77289,14 +91377,14 @@ typedef struct hwrm_mfg_soc_qstatus_output { uint8_t valid; } hwrm_mfg_soc_qstatus_output_t, *phwrm_mfg_soc_qstatus_output_t; -/******************************* - * hwrm_mfg_param_seeprom_sync * - *******************************/ +/***************************************** + * hwrm_mfg_param_critical_data_finalize * + *****************************************/ -/* hwrm_mfg_param_seeprom_sync_input (size:640b/80B) */ +/* hwrm_mfg_param_critical_data_finalize_input (size:192b/24B) */ -typedef struct hwrm_mfg_param_seeprom_sync_input { +typedef struct hwrm_mfg_param_critical_data_finalize_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -77325,34 +91413,19 @@ typedef struct hwrm_mfg_param_seeprom_sync_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; + uint16_t flags; /* - * The host (DMA) buffer physical addr for the firmware to read from. - * This buffer is populated with the parameter binary bits which is - * going to be programmed into the seeprom memory. - */ - uint64_t data_addr; - /* Size of the buffer pointed to by data_addr. */ - uint16_t data_len; - /* The offset within the SEEPROM to start programming. */ - uint16_t offset; - uint32_t flags; - /* - * This bit must be '1' to sync the parameters available in factory - * config to seeprom binary before writing to seeprom - */ - #define HWRM_MFG_PARAM_SEEPROM_SYNC_INPUT_FLAGS_FAC_CFG_SYNC UINT32_C(0x1) - /* - * This bit must be '1' for the seeprom data to be written to - * a specified address with out any change in the binary + * Set to 1 if you wish to unlock and erase the region + * before finalizing the data. */ - #define HWRM_MFG_PARAM_SEEPROM_SYNC_INPUT_FLAGS_WRITE_BINARY_ONLY UINT32_C(0x80000000) - /* Reserved for future use. */ - uint8_t reserved[48]; -} hwrm_mfg_param_seeprom_sync_input_t, *phwrm_mfg_param_seeprom_sync_input_t; + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE_INPUT_FLAGS_FORCE UINT32_C(0x1) + uint16_t unused_0; + uint32_t unused_1; +} hwrm_mfg_param_critical_data_finalize_input_t, *phwrm_mfg_param_critical_data_finalize_input_t; -/* hwrm_mfg_param_seeprom_sync_output (size:128b/16B) */ +/* hwrm_mfg_param_critical_data_finalize_output (size:128b/16B) */ -typedef struct hwrm_mfg_param_seeprom_sync_output { +typedef struct hwrm_mfg_param_critical_data_finalize_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -77361,28 +91434,36 @@ typedef struct hwrm_mfg_param_seeprom_sync_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Total length of data written to the seeprom memory. */ - uint16_t total_data_len; - uint16_t unused_0; - uint8_t unused_1[3]; + /* Total length of data finalized. */ + uint32_t total_data_len; + uint16_t error_status; + /* Critical data region was already locked */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE_OUTPUT_ERROR_STATUS_ALREADY_LOCKED UINT32_C(0x1) + /* Flash region was not entirely empty */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE_OUTPUT_ERROR_STATUS_NOT_EMPTY UINT32_C(0x2) + /* FACT_CFG was missing for write to critical cfg */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE_OUTPUT_ERROR_STATUS_MISSING_FACT_CFG UINT32_C(0x4) + /* VPD was missing for write to critical cfg */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_FINALIZE_OUTPUT_ERROR_STATUS_MISSING_VPD UINT32_C(0x8) + uint8_t unused_1; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; -} hwrm_mfg_param_seeprom_sync_output_t, *phwrm_mfg_param_seeprom_sync_output_t; +} hwrm_mfg_param_critical_data_finalize_output_t, *phwrm_mfg_param_critical_data_finalize_output_t; -/******************************* - * hwrm_mfg_param_seeprom_read * - *******************************/ +/************************************* + * hwrm_mfg_param_critical_data_read * + *************************************/ -/* hwrm_mfg_param_seeprom_read_input (size:256b/32B) */ +/* hwrm_mfg_param_critical_data_read_input (size:256b/32B) */ -typedef struct hwrm_mfg_param_seeprom_read_input { +typedef struct hwrm_mfg_param_critical_data_read_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -77413,8 +91494,8 @@ typedef struct hwrm_mfg_param_seeprom_read_input { uint64_t resp_addr; /* * The host (DMA) buffer physical addr for the firmware to write to. - * This buffer is populated with the parameter binary bits which is - * going to be read from the seeprom memory. + * This buffer is populated with data read from the + * critical data storage location. */ uint64_t data_addr; /* @@ -77422,15 +91503,14 @@ typedef struct hwrm_mfg_param_seeprom_read_input { * use this entire buffer or less than the entire buffer, but never * more. */ - uint16_t data_len; - /* The offset within the SEEPROM to start reading. */ - uint16_t offset; - uint8_t unused[4]; -} hwrm_mfg_param_seeprom_read_input_t, *phwrm_mfg_param_seeprom_read_input_t; + uint32_t data_len; + /* The offset within the critical data to start reading. */ + uint32_t offset; +} hwrm_mfg_param_critical_data_read_input_t, *phwrm_mfg_param_critical_data_read_input_t; -/* hwrm_mfg_param_seeprom_read_output (size:128b/16B) */ +/* hwrm_mfg_param_critical_data_read_output (size:128b/16B) */ -typedef struct hwrm_mfg_param_seeprom_read_output { +typedef struct hwrm_mfg_param_critical_data_read_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -77440,27 +91520,27 @@ typedef struct hwrm_mfg_param_seeprom_read_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; /* Total length of data written to the host memory. */ - uint16_t total_data_len; - uint16_t unused_0[2]; + uint32_t total_data_len; + uint16_t unused_0; + uint8_t unused_1; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; - uint8_t unused_1; -} hwrm_mfg_param_seeprom_read_output_t, *phwrm_mfg_param_seeprom_read_output_t; +} hwrm_mfg_param_critical_data_read_output_t, *phwrm_mfg_param_critical_data_read_output_t; -/********************************* - * hwrm_mfg_param_seeprom_health * - *********************************/ +/*************************************** + * hwrm_mfg_param_critical_data_health * + ***************************************/ -/* hwrm_mfg_param_seeprom_health_input (size:192b/24B) */ +/* hwrm_mfg_param_critical_data_health_input (size:192b/24B) */ -typedef struct hwrm_mfg_param_seeprom_health_input { +typedef struct hwrm_mfg_param_critical_data_health_input { /* The HWRM command request type. */ uint16_t req_type; /* @@ -77490,11 +91570,11 @@ typedef struct hwrm_mfg_param_seeprom_health_input { */ uint64_t resp_addr; uint64_t unused_0; -} hwrm_mfg_param_seeprom_health_input_t, *phwrm_mfg_param_seeprom_health_input_t; +} hwrm_mfg_param_critical_data_health_input_t, *phwrm_mfg_param_critical_data_health_input_t; -/* hwrm_mfg_param_seeprom_health_output (size:128b/16B) */ +/* hwrm_mfg_param_critical_data_health_output (size:128b/16B) */ -typedef struct hwrm_mfg_param_seeprom_health_output { +typedef struct hwrm_mfg_param_critical_data_health_output { /* The specific error status for the command. */ uint16_t error_code; /* The HWRM command request type. */ @@ -77504,37 +91584,25 @@ typedef struct hwrm_mfg_param_seeprom_health_output { /* The length of the response data in number of bytes. */ uint16_t resp_len; uint32_t health_status; - /* No response from the device */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_NO_RESPONSE UINT32_C(0x1) + /* region entirely empty */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH_OUTPUT_HEALTH_STATUS_IS_EMPTY UINT32_C(0x1) /* Data checksum fail */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_CHECKSUM_FAIL UINT32_C(0x2) - /* Mac address not populated */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_NO_MAC_ADDRESS UINT32_C(0x4) - /* Part number not populated */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_NO_PART_NUMBER UINT32_C(0x8) - /* Serial number not populated */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_NO_SR_NUMBER UINT32_C(0x10) - /* Package description not populated */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_STATUS_NO_PKG_DESCRIPTION UINT32_C(0x20) - uint16_t health_code; - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_SUCCESS UINT32_C(0x0) - /* No response from the device */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_NO_RESPONSE UINT32_C(0x1) - /* Data checksum fail */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_CHECKSUM_FAIL UINT32_C(0x2) - /* Mac address not populated */ - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_NO_MAC_ADDRESS UINT32_C(0x3) - #define HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_LAST HWRM_MFG_PARAM_SEEPROM_HEALTH_OUTPUT_HEALTH_CODE_NO_MAC_ADDRESS + #define HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH_OUTPUT_HEALTH_STATUS_CHECKSUM_FAIL UINT32_C(0x2) + /* Malformed data (header/footer) */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH_OUTPUT_HEALTH_STATUS_MALFORMED_DATA UINT32_C(0x4) + /* Critical data not locked */ + #define HWRM_MFG_PARAM_CRITICAL_DATA_HEALTH_OUTPUT_HEALTH_STATUS_NOT_LOCKED UINT32_C(0x8) + uint16_t unused_1; + uint8_t unused_2; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; - uint8_t unused_1; -} hwrm_mfg_param_seeprom_health_output_t, *phwrm_mfg_param_seeprom_health_output_t; +} hwrm_mfg_param_critical_data_health_output_t, *phwrm_mfg_param_critical_data_health_output_t; /***************************** * hwrm_mfg_prvsn_export_csr * @@ -77573,16 +91641,24 @@ typedef struct hwrm_mfg_prvsn_export_csr_input { */ uint64_t resp_addr; /* - * 64-bit Host destination address. This is the host address where + * 64-bit Host destination address. This is the host address where * data will be written. */ uint64_t host_dest_addr; - /* Provisioning slot number. 0-indexed. */ + /* Provisioning slot number. 0-indexed. */ uint8_t slot; uint8_t unused_0; /* Size in bytes of the available host buffer. */ uint16_t host_buf_len; - uint32_t unused_1; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used for + * secure boot. If this bit is set, export a certificate signing + * request (CSR) from the security SoC non-volatile storage on + * the device. + */ + #define HWRM_MFG_PRVSN_EXPORT_CSR_INPUT_FLAGS_SECURE_SOC_SUPPORT UINT32_C(0x1) + uint8_t unused_1[3]; } hwrm_mfg_prvsn_export_csr_input_t, *phwrm_mfg_prvsn_export_csr_input_t; /* hwrm_mfg_prvsn_export_csr_output (size:128b/16B) */ @@ -77596,7 +91672,7 @@ typedef struct hwrm_mfg_prvsn_export_csr_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Provisioning slot number. 0-indexed. */ + /* Provisioning slot number. 0-indexed. */ uint8_t slot; uint8_t unused_0; /* Size in bytes of the exported CSR. */ @@ -77604,7 +91680,7 @@ typedef struct hwrm_mfg_prvsn_export_csr_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77668,16 +91744,24 @@ typedef struct hwrm_mfg_prvsn_import_cert_input { */ uint64_t resp_addr; /* - * 64-bit Host source address. This is the host address where + * 64-bit Host source address. This is the host address where * source data is located. */ uint64_t host_src_addr; - /* Provisioning slot number. 0-indexed. */ + /* Provisioning slot number. 0-indexed. */ uint8_t slot; uint8_t unused_0; /* Size in bytes of the certificate chain. */ uint16_t cert_len; - uint32_t unused_1; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used for + * secure boot. If this bit is set, then import a HSM-signed + * certificate chain to security SoC non-volatile storage on + * the device. + */ + #define HWRM_MFG_PRVSN_IMPORT_CERT_INPUT_FLAGS_SECURE_SOC_SUPPORT UINT32_C(0x1) + uint8_t unused_1[3]; } hwrm_mfg_prvsn_import_cert_input_t, *phwrm_mfg_prvsn_import_cert_input_t; /* hwrm_mfg_prvsn_import_cert_output (size:128b/16B) */ @@ -77691,7 +91775,7 @@ typedef struct hwrm_mfg_prvsn_import_cert_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - /* Provisioning slot number. 0-indexed. */ + /* Provisioning slot number. 0-indexed. */ uint8_t slot; /* Provisioned state */ uint8_t state; @@ -77703,7 +91787,7 @@ typedef struct hwrm_mfg_prvsn_import_cert_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77788,7 +91872,7 @@ typedef struct hwrm_mfg_prvsn_get_state_output { /* Flag indicating if provision get state is valid. */ uint8_t get_state_valid; /* - * Provision get state is invalid. The attestation agent has not + * Provision get state is invalid. The attestation agent has not * yet initialized and not completed verification of the * provisioned certificate chain. * The slot_status field is undetermined. @@ -77798,7 +91882,7 @@ typedef struct hwrm_mfg_prvsn_get_state_output { #define HWRM_MFG_PRVSN_GET_STATE_OUTPUT_GET_STATE_VALID_SPDM UINT32_C(0x1) /* Provision get state is valid for Cerberus. */ #define HWRM_MFG_PRVSN_GET_STATE_OUTPUT_GET_STATE_VALID_CERBERUS UINT32_C(0x2) - /* Provision get state is valid. There is no attestation agent. */ + /* Provision get state is valid. There is no attestation agent. */ #define HWRM_MFG_PRVSN_GET_STATE_OUTPUT_GET_STATE_VALID_NONE UINT32_C(0xff) #define HWRM_MFG_PRVSN_GET_STATE_OUTPUT_GET_STATE_VALID_LAST HWRM_MFG_PRVSN_GET_STATE_OUTPUT_GET_STATE_VALID_NONE /* @@ -77822,7 +91906,7 @@ typedef struct hwrm_mfg_prvsn_get_state_output { uint8_t unused_0[5]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77831,6 +91915,118 @@ typedef struct hwrm_mfg_prvsn_get_state_output { uint8_t valid; } hwrm_mfg_prvsn_get_state_output_t, *phwrm_mfg_prvsn_get_state_output_t; +/****************************** + * hwrm_mfg_prvsn_export_cert * + ******************************/ + + +/* hwrm_mfg_prvsn_export_cert_input (size:256b/32B) */ + +typedef struct hwrm_mfg_prvsn_export_cert_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * 64-bit Host destination address. This is the host address where + * data will be written. + */ + uint64_t host_dest_addr; + /* Provisioning slot number. 0-indexed. */ + uint8_t slot; + uint8_t unused_0; + /* Size in bytes of the available host buffer. */ + uint16_t host_buf_len; + uint8_t flags; + /* + * This bit is only used when external secure SoC is used + * for secure boot. If this bit is set, then export the + * provisioned certificate from the security SoC non-volatile + * storage device. + */ + #define HWRM_MFG_PRVSN_EXPORT_CERT_INPUT_FLAGS_SECURE_SOC_SUPPORT UINT32_C(0x1) + uint8_t unused_1[3]; +} hwrm_mfg_prvsn_export_cert_input_t, *phwrm_mfg_prvsn_export_cert_input_t; + +/* hwrm_mfg_prvsn_export_cert_output (size:128b/16B) */ + +typedef struct hwrm_mfg_prvsn_export_cert_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* Provisioning slot number. 0-indexed. */ + uint8_t slot; + uint8_t unused_0; + /* + * Size in bytes of the exported certificate chain. If there are no + * certificates provisioned for the specified slot, the device will + * return a successful response with cert_len equal to 0. + */ + uint16_t cert_len; + uint8_t unused_1[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. + * When writing a command completion or response to an internal + * processor, the order of writes has to be such that this field is + * written last. + */ + uint8_t valid; +} hwrm_mfg_prvsn_export_cert_output_t, *phwrm_mfg_prvsn_export_cert_output_t; + +/* hwrm_mfg_prvsn_export_cert_cmd_err (size:64b/8B) */ + +typedef struct hwrm_mfg_prvsn_export_cert_cmd_err { + /* + * command specific error codes that goes to + * the cmd_err field in Common HWRM Error Response. + */ + uint8_t code; + /* Unknown error. */ + #define HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_UNKNOWN UINT32_C(0x0) + /* Slot invalid */ + #define HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_SLOT_INVALID UINT32_C(0x1) + /* + * The provisioned certificates are invalid due to device ID change, + * NVRAM corruption or another reason. + */ + #define HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_CERT_INVALID UINT32_C(0x2) + /* Host provided buffer is too small */ + #define HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_BUFFER_LENGTH UINT32_C(0x3) + #define HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_LAST HWRM_MFG_PRVSN_EXPORT_CERT_CMD_ERR_CODE_BUFFER_LENGTH + uint8_t unused_0[7]; +} hwrm_mfg_prvsn_export_cert_cmd_err_t, *phwrm_mfg_prvsn_export_cert_cmd_err_t; + /******************************** * hwrm_mfg_get_nvm_measurement * ********************************/ @@ -77869,7 +92065,7 @@ typedef struct hwrm_mfg_get_nvm_measurement_input { uint64_t resp_addr; } hwrm_mfg_get_nvm_measurement_input_t, *phwrm_mfg_get_nvm_measurement_input_t; -/* hwrm_mfg_get_nvm_measurement_output (size:448b/56B) */ +/* hwrm_mfg_get_nvm_measurement_output (size:704b/88B) */ typedef struct hwrm_mfg_get_nvm_measurement_output { /* The specific error status for the command. */ @@ -77883,7 +92079,7 @@ typedef struct hwrm_mfg_get_nvm_measurement_output { /* Flag indicating if the hash returned is valid. */ uint8_t hash_state; /* - * Measurement hash is invalid. There was an error + * Measurement hash is invalid. There was an error * calculating the hash or firmware does not support NVM * measurement. */ @@ -77901,13 +92097,22 @@ typedef struct hwrm_mfg_get_nvm_measurement_output { /* Measurement is calculated in real time */ #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_CALC_TIME_LIVE UINT32_C(0x1) #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_CALC_TIME_LAST HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_CALC_TIME_LIVE - uint8_t unused_0[6]; - /* Thirty two bytes HMAC SHA256 hash of NVM configuration. */ - uint8_t hash[32]; + /* Flag indicating the hash type when hash_state is valid. */ + uint8_t hash_type; + /* Measurement hash is SHA256(32 bytes). */ + #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_HASH_TYPE_SHA256 UINT32_C(0x0) + /* Measurement hash is SHA384(48 bytes). */ + #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_HASH_TYPE_SHA384 UINT32_C(0x1) + /* Measurement hash is SHA512(64 bytes). */ + #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_HASH_TYPE_SHA512 UINT32_C(0x2) + #define HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_HASH_TYPE_LAST HWRM_MFG_GET_NVM_MEASUREMENT_OUTPUT_HASH_TYPE_SHA512 + uint8_t unused_0[5]; + /* NVM configuration hash with length indicated by hash_type. */ + uint8_t hash[64]; uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -77998,7 +92203,7 @@ typedef struct hwrm_mfg_psoc_qstatus_output { uint8_t unused_2[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' + * is completely written to RAM. This field should be read as '1' * to indicate that the output has been completely written. * When writing a command completion or response to an internal * processor, the order of writes has to be such that this field is @@ -78097,9 +92302,9 @@ typedef struct hwrm_mfg_selftest_qlist_output { uint8_t unused_2[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -78249,9 +92454,9 @@ typedef struct hwrm_mfg_selftest_exec_output { uint8_t unused_1[3]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -78293,8 +92498,29 @@ typedef struct hwrm_oem_cmd_input { * point to a physically contiguous block of memory. */ uint64_t resp_addr; - uint32_t IANA; - uint32_t unused_0; + /* + * The organization owning the message format. Set this field + * to 0x14e4 when used for Broadcom internal use when + * the naming authority is set to PCI_SIG. + */ + uint32_t oem_id; + /* The naming authority used for setting the oem_id. */ + uint8_t naming_authority; + /* Invalid naming authority */ + #define HWRM_OEM_CMD_INPUT_NAMING_AUTHORITY_INVALID UINT32_C(0x0) + /* PCI_SIG naming authority numbering is used */ + #define HWRM_OEM_CMD_INPUT_NAMING_AUTHORITY_PCI_SIG UINT32_C(0x1) + #define HWRM_OEM_CMD_INPUT_NAMING_AUTHORITY_LAST HWRM_OEM_CMD_INPUT_NAMING_AUTHORITY_PCI_SIG + /* The message family within the organization. */ + uint8_t message_family; + /* Invalid message family */ + #define HWRM_OEM_CMD_INPUT_MESSAGE_FAMILY_INVALID UINT32_C(0x0) + /* This message is targeted for Truflow */ + #define HWRM_OEM_CMD_INPUT_MESSAGE_FAMILY_TRUFLOW UINT32_C(0x1) + /* This message is targeted for RoCE */ + #define HWRM_OEM_CMD_INPUT_MESSAGE_FAMILY_ROCE UINT32_C(0x2) + #define HWRM_OEM_CMD_INPUT_MESSAGE_FAMILY_LAST HWRM_OEM_CMD_INPUT_MESSAGE_FAMILY_ROCE + uint16_t unused; /* This field contains the vendor specific command data. */ uint32_t oem_data[26]; } hwrm_oem_cmd_input_t, *phwrm_oem_cmd_input_t; @@ -78310,16 +92536,21 @@ typedef struct hwrm_oem_cmd_output { uint16_t seq_id; /* The length of the response data in number of bytes. */ uint16_t resp_len; - uint32_t IANA; - uint32_t unused_0; + /* The organization owning the message format. */ + uint32_t oem_id; + /* The naming authority used for setting the oem_id. */ + uint8_t naming_authority; + /* The message family within the organization. */ + uint8_t message_family; + uint16_t unused; /* This field contains the vendor specific response data. */ uint32_t oem_data[18]; uint8_t unused_1[7]; /* * This field is used in Output records to indicate that the output - * is completely written to RAM. This field should be read as '1' - * to indicate that the output has been completely written. - * When writing a command completion or response to an internal processor, + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, * the order of writes has to be such that this field is written last. */ uint8_t valid; @@ -78378,4 +92609,820 @@ typedef struct hwrm_sv_output { uint32_t opaque[32]; } hwrm_sv_output_t, *phwrm_sv_output_t; +/******************* + * hwrm_udcc_qcaps * + *******************/ + + +/* hwrm_udcc_qcaps_input (size:128b/16B) */ + +typedef struct hwrm_udcc_qcaps_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_udcc_qcaps_input_t, *phwrm_udcc_qcaps_input_t; + +/* hwrm_udcc_qcaps_output (size:192b/24B) */ + +typedef struct hwrm_udcc_qcaps_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This field represents guaranteed minimum number of UDCC sessions + * available to the function. + */ + uint16_t min_sessions; + /* + * This field represents unguaranteed maximum number of UDCC sessions + * available to the function. + */ + uint16_t max_sessions; + /* + * This value indicates the type of session being modified by the + * UDCC. + */ + uint8_t session_type; + /* sessions are allocated on a per destination basis. */ + #define HWRM_UDCC_QCAPS_OUTPUT_SESSION_TYPE_PER_DESTINATION UINT32_C(0x0) + /* sessions are allocated on a per QP basis. */ + #define HWRM_UDCC_QCAPS_OUTPUT_SESSION_TYPE_PER_QP UINT32_C(0x1) + #define HWRM_UDCC_QCAPS_OUTPUT_SESSION_TYPE_LAST HWRM_UDCC_QCAPS_OUTPUT_SESSION_TYPE_PER_QP + uint8_t unused_0[3]; + /* + * This field represents the maximum number of bytes of UDCC program + * configuration data that one hwrm_udcc_comp_cfg request or + * hwrm_udcc_comp_qcfg response can transfer. + * The value is determined by the UDCC firmware. + */ + uint16_t max_comp_cfg_xfer; + /* + * This field represents the maximum number of bytes of UDCC program + * status or statistics data that one hwrm_udcc_comp_query response + * can transfer. The value is determined by the UDCC firmware. + */ + uint16_t max_comp_data_xfer; + uint8_t unused_1[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_qcaps_output_t, *phwrm_udcc_qcaps_output_t; + +/***************** + * hwrm_udcc_cfg * + *****************/ + + +/* hwrm_udcc_cfg_input (size:192b/24B) */ + +typedef struct hwrm_udcc_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* + * This bit must be '1' for the udcc_mode field to be + * configured. + */ + #define HWRM_UDCC_CFG_INPUT_ENABLES_UDCC_MODE UINT32_C(0x1) + /* UDCC mode for this function. */ + uint8_t udcc_mode; + /* UDCC is not enabled. */ + #define HWRM_UDCC_CFG_INPUT_UDCC_MODE_DISABLED UINT32_C(0x0) + /* UDCC is enabled. */ + #define HWRM_UDCC_CFG_INPUT_UDCC_MODE_ENABLED UINT32_C(0x1) + #define HWRM_UDCC_CFG_INPUT_UDCC_MODE_LAST HWRM_UDCC_CFG_INPUT_UDCC_MODE_ENABLED + uint8_t unused_1[3]; +} hwrm_udcc_cfg_input_t, *phwrm_udcc_cfg_input_t; + +/* hwrm_udcc_cfg_output (size:128b/16B) */ + +typedef struct hwrm_udcc_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_cfg_output_t, *phwrm_udcc_cfg_output_t; + +/****************** + * hwrm_udcc_qcfg * + ******************/ + + +/* hwrm_udcc_qcfg_input (size:128b/16B) */ + +typedef struct hwrm_udcc_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; +} hwrm_udcc_qcfg_input_t, *phwrm_udcc_qcfg_input_t; + +/* hwrm_udcc_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_udcc_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* UDCC mode for this function. */ + uint8_t udcc_mode; + uint8_t unused_1[6]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_qcfg_output_t, *phwrm_udcc_qcfg_output_t; + +/************************* + * hwrm_udcc_session_cfg * + *************************/ + + +/* hwrm_udcc_session_cfg_input (size:384b/48B) */ + +typedef struct hwrm_udcc_session_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + uint32_t enables; + /* This bit must be '1' for the session_state to be configured. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_ENABLES_SESSION_STATE UINT32_C(0x1) + /* This bit must be '1' for the dest_mac to be configured. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_ENABLES_DEST_MAC UINT32_C(0x2) + /* This bit must be '1' for the src_mac to be configured. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_ENABLES_SRC_MAC UINT32_C(0x4) + /* This bit must be '1' for the tx_stats_record to be configured. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_ENABLES_TX_STATS_RECORD UINT32_C(0x8) + /* This bit must be '1' for the rx_stats_record to be configured. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_ENABLES_RX_STATS_RECORD UINT32_C(0x10) + /* State to configure for the session. */ + uint8_t session_state; + /* + * This bit is set if the session is to be enabled and have firmware + * querying it for events. The bit is cleared if the session is to + * be disabled in firmware. + */ + #define HWRM_UDCC_SESSION_CFG_INPUT_SESSION_STATE_ENABLED UINT32_C(0x1) + /* UDCC flow is not created in driver. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_SESSION_STATE_FLOW_NOT_CREATED UINT32_C(0x2) + /* UDCC flow is now deleted in driver. */ + #define HWRM_UDCC_SESSION_CFG_INPUT_SESSION_STATE_FLOW_HAS_BEEN_DELETED UINT32_C(0x4) + uint8_t unused_1; + /* A handle for the session to be configured, if previously allocated. */ + uint16_t session_id; + /* destination mac address used for the session. */ + uint8_t dest_mac[6]; + uint16_t unused_2; + /* source mac address used for the session. */ + uint8_t src_mac[6]; + uint16_t unused_3; + /* + * address for the tx flow statistics record to be sampled by the + * UDCC firmware. Session must be disabled to take effect. + */ + uint32_t tx_stats_record; + /* + * address for the rx flow statistics record to be sampled by the + * UDCC firmware. Session must be disabled to take effect. + */ + uint32_t rx_stats_record; +} hwrm_udcc_session_cfg_input_t, *phwrm_udcc_session_cfg_input_t; + +/* hwrm_udcc_session_cfg_output (size:128b/16B) */ + +typedef struct hwrm_udcc_session_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_session_cfg_output_t, *phwrm_udcc_session_cfg_output_t; + +/************************** + * hwrm_udcc_session_qcfg * + **************************/ + + +/* hwrm_udcc_session_qcfg_input (size:192b/24B) */ + +typedef struct hwrm_udcc_session_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* A handle for the session to be queried, if previously allocated. */ + uint16_t session_id; + uint8_t unused_0[6]; +} hwrm_udcc_session_qcfg_input_t, *phwrm_udcc_session_qcfg_input_t; + +/* hwrm_udcc_session_qcfg_output (size:512b/64B) */ + +typedef struct hwrm_udcc_session_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* session_state specifying configuration of the session. */ + uint8_t session_state; + /* + * This bit is set if the session is enabled and firmware is + * querying it for events. The bit is cleared if no querying + * should occur for this session. + */ + #define HWRM_UDCC_SESSION_QCFG_OUTPUT_SESSION_STATE_ENABLED UINT32_C(0x1) + /* UDCC flow is not created in driver. */ + #define HWRM_UDCC_SESSION_QCFG_OUTPUT_SESSION_STATE_FLOW_NOT_CREATED UINT32_C(0x2) + /* UDCC flow is now deleted in driver. */ + #define HWRM_UDCC_SESSION_QCFG_OUTPUT_SESSION_STATE_FLOW_HAS_BEEN_DELETED UINT32_C(0x4) + uint8_t unused_0; + /* destination mac address used for the session. */ + uint8_t dest_mac[6]; + /* + * a 4 byte or 16 byte IP address, depending on whether the ip_type + * specifies IPv4 or IPv6. For IPv4 addresses, the first 4 bytes of the + * 16 byte field are used; the remaining 12 bytes are not used. + */ + uint32_t dest_ip[4]; + uint8_t unused_1[2]; + /* source mac address used for the session. */ + uint8_t src_mac[6]; + /* source QP number used for the session. */ + uint32_t src_qp_num; + /* destination QP number used for the session. */ + uint32_t dest_qp_num; + /* + * address for the tx flow statistics record to be sampled by the + * UDCC firmware. + */ + uint32_t tx_stats_record; + /* + * address for the rx flow statistics record to be sampled by the + * UDCC firmware. + */ + uint32_t rx_stats_record; + uint8_t unused_2[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_session_qcfg_output_t, *phwrm_udcc_session_qcfg_output_t; + +/*************************** + * hwrm_udcc_session_query * + ***************************/ + + +/* hwrm_udcc_session_query_input (size:192b/24B) */ + +typedef struct hwrm_udcc_session_query_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* A handle for the session to be queried, if previously allocated. */ + uint16_t session_id; + uint8_t unused_0[6]; +} hwrm_udcc_session_query_input_t, *phwrm_udcc_session_query_input_t; + +/* hwrm_udcc_session_query_output (size:640b/80B) */ + +typedef struct hwrm_udcc_session_query_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* field for the minimum RTT value (in ns) for the session. */ + uint32_t min_rtt_ns; + /* field for the maximum RTT value (in ns) for the session. */ + uint32_t max_rtt_ns; + /* + * field for the current configured rate (in Mbps) for the + * session. + */ + uint32_t cur_rate_mbps; + /* + * count for the number of events sent from FW to the UDCC + * program. + */ + uint32_t tx_event_count; + /* + * count for the number of CNP events sent from FW to the UDCC + * program. + */ + uint32_t cnp_rx_event_count; + /* + * count for the number of RTT request events received by the FW from + * the UDCC program. + */ + uint32_t rtt_req_count; + /* + * count for the number of RTT response events sent by the FW to the + * UDCC program. + */ + uint32_t rtt_resp_count; + /* count for the number of bytes transmitted for the session. */ + uint32_t tx_bytes_count; + /* count for the number of packets transmitted for the session. */ + uint32_t tx_packets_count; + /* count of initiator probes transmitted for the session. */ + uint32_t init_probes_sent; + /* count of terminator probes received for the session. */ + uint32_t term_probes_recv; + /* count of CNP packets received for the session. */ + uint32_t cnp_packets_recv; + /* count of retransmission timeout events received for the session. */ + uint32_t rto_event_recv; + /* count of sequence error NAK events received for the session. */ + uint32_t seq_err_nak_recv; + /* the current number of qps associated with the session. */ + uint32_t qp_count; + /* count for the number of Tx events detected for the session. */ + uint32_t tx_event_detect_count; + uint8_t unused_1[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_session_query_output_t, *phwrm_udcc_session_query_output_t; + +/********************** + * hwrm_udcc_comp_cfg * + **********************/ + + +/* hwrm_udcc_comp_cfg_input (size:576b/72B) */ + +typedef struct hwrm_udcc_comp_cfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * This field holds the configuration arguments, which can be used + * to specify the context of the configuration data, e.g. type, + * session ID, etc. It is possible not all arg_buf are utilized. + * The format and meaning of the arguments are internal to + * the UDCC program. + */ + uint8_t arg_buf[40]; + /* + * This field specifies the number of bytes in arg_buf that are + * configuration arguments. It can be zero if there are no arguments. + */ + uint32_t arg_len; + /* + * This field specifies the length of the configuration data + * stored in the host memory. The host driver shall guarantee + * this number is not greater than the maximum configuration + * transfer size that is specified by the max_comp_cfg_xfer + * field of hwrm_udcc_qcaps_output. + */ + uint32_t cfg_len; + /* + * This field specifies the address of the host memory where + * the configuration data is stored. The format and meaning of + * the configuration data are internal to the UDCC program. + */ + uint64_t cfg_host_addr; +} hwrm_udcc_comp_cfg_input_t, *phwrm_udcc_comp_cfg_input_t; + +/* hwrm_udcc_comp_cfg_output (size:128b/16B) */ + +typedef struct hwrm_udcc_comp_cfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + uint8_t unused_0[7]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_comp_cfg_output_t, *phwrm_udcc_comp_cfg_output_t; + +/*********************** + * hwrm_udcc_comp_qcfg * + ***********************/ + + +/* hwrm_udcc_comp_qcfg_input (size:576b/72B) */ + +typedef struct hwrm_udcc_comp_qcfg_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * This field holds the query arguments, which can be used to + * specify the context of the query, e.g. type, session ID, etc. + * It is possible not all arg_buf are utilized. + * The format and meaning of the arguments are internal to + * the UDCC program. + */ + uint8_t arg_buf[40]; + /* + * This field specifies the number of bytes in arg_buf that are + * query arguments. It can be zero if there are no arguments. + */ + uint32_t arg_len; + /* + * This field specifies the size of the buffer in the host memory + * for receiving the configuration data. The host driver shall + * guarantee the size of the buffer is not smaller than + * the maximum configuration transfer size that is specified by + * the max_comp_cfg_xfer field of hwrm_udcc_qcaps_output. + */ + uint32_t cfg_host_buf_size; + /* + * This field specifies the address of the host memory where + * the queried configuration to be stored. + */ + uint64_t cfg_host_addr; +} hwrm_udcc_comp_qcfg_input_t, *phwrm_udcc_comp_qcfg_input_t; + +/* hwrm_udcc_comp_qcfg_output (size:128b/16B) */ + +typedef struct hwrm_udcc_comp_qcfg_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This field specifies the length of configuration data transferred + * into the host memory. The amount of data transferred is up to + * the maximum configuration transfer size that is specified by + * the max_comp_cfg_xfer field of hwrm_udcc_qcaps_output. + */ + uint32_t cfg_len; + uint8_t unused_0[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_comp_qcfg_output_t, *phwrm_udcc_comp_qcfg_output_t; + +/************************ + * hwrm_udcc_comp_query * + ************************/ + + +/* hwrm_udcc_comp_query_input (size:576b/72B) */ + +typedef struct hwrm_udcc_comp_query_input { + /* The HWRM command request type. */ + uint16_t req_type; + /* + * The completion ring to send the completion event on. This should + * be the NQ ID returned from the `nq_alloc` HWRM command. + */ + uint16_t cmpl_ring; + /* + * The sequence ID is used by the driver for tracking multiple + * commands. This ID is treated as opaque data by the firmware and + * the value is returned in the `hwrm_resp_hdr` upon completion. + */ + uint16_t seq_id; + /* + * The target ID of the command: + * * 0x0-0xFFF8 - The function ID + * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors + * * 0xFFFD - Reserved for user-space HWRM interface + * * 0xFFFF - HWRM + */ + uint16_t target_id; + /* + * A physical address pointer pointing to a host buffer that the + * command's response data will be written. This can be either a host + * physical address (HPA) or a guest physical address (GPA) and must + * point to a physically contiguous block of memory. + */ + uint64_t resp_addr; + /* + * This field holds the query arguments, which can be used to + * specify the context of the query, e.g. type, session ID, etc. + * It is possible not all arg_buf are utilized. + * The format and meaning of the arguments are internal to + * the UDCC program. + */ + uint8_t arg_buf[40]; + /* + * This field specifies the number of bytes in arg_buf that are + * query arguments. It can be zero if there are no arguments. + */ + uint32_t arg_len; + /* + * This field specifies the size of the buffer in the host memory + * for receiving the status or statistics data. The host driver + * shall guarantee the size of the buffer is not smaller than + * the maximum data transfer size that is specified by + * the max_comp_data_xfer field of hwrm_udcc_qcaps_output. + */ + uint32_t data_host_buf_size; + /* + * This field specifies the address of the host memory where + * the queried data to be stored. + */ + uint64_t data_host_addr; +} hwrm_udcc_comp_query_input_t, *phwrm_udcc_comp_query_input_t; + +/* hwrm_udcc_comp_query_output (size:128b/16B) */ + +typedef struct hwrm_udcc_comp_query_output { + /* The specific error status for the command. */ + uint16_t error_code; + /* The HWRM command request type. */ + uint16_t req_type; + /* The sequence ID from the original command. */ + uint16_t seq_id; + /* The length of the response data in number of bytes. */ + uint16_t resp_len; + /* + * This field specifies the length of status or statistics data + * transferred into the host memory. The amount of data transferred + * is up to the maximum data transfer size that is specified by + * the max_comp_data_xfer field of hwrm_udcc_qcaps_output. + */ + uint32_t data_len; + uint8_t unused_0[3]; + /* + * This field is used in Output records to indicate that the output + * is completely written to RAM. This field should be read as '1' + * to indicate that the output has been completely written. When + * writing a command completion or response to an internal processor, + * the order of writes has to be such that this field is written last. + */ + uint8_t valid; +} hwrm_udcc_comp_query_output_t, *phwrm_udcc_comp_query_output_t; + #endif /* _HSI_STRUCT_DEF_H_ */ diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c index 9fd76301d6b3..feac3ce54a29 100644 --- a/sys/dev/bnxt/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -40,7 +40,6 @@ #include <machine/resource.h> #include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> #include <net/if.h> #include <net/if_dl.h> @@ -49,6 +48,14 @@ #include <net/ethernet.h> #include <net/iflib.h> +#include <linux/pci.h> +#include <linux/kmod.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/idr.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/rcupdate.h> #include "opt_inet.h" #include "opt_inet6.h" #include "opt_rss.h" @@ -61,6 +68,8 @@ #include "bnxt_sysctl.h" #include "hsi_struct_def.h" #include "bnxt_mgmt.h" +#include "bnxt_ulp.h" +#include "bnxt_auxbus_compat.h" /* * PCI Device ID Table @@ -134,8 +143,18 @@ static const pci_vendor_info_t bnxt_vendor_info_array[] = "Broadcom BCM57508 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet"), PVID(BROADCOM_VENDOR_ID, BCM57504, "Broadcom BCM57504 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet"), + PVID(BROADCOM_VENDOR_ID, BCM57504_NPAR, + "Broadcom BCM57504 NetXtreme-E Ethernet Partition"), PVID(BROADCOM_VENDOR_ID, BCM57502, "Broadcom BCM57502 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet"), + PVID(BROADCOM_VENDOR_ID, BCM57608, + "Broadcom BCM57608 NetXtreme-E 25Gb/50Gb/100Gb/200Gb/400Gb Ethernet"), + PVID(BROADCOM_VENDOR_ID, BCM57604, + "Broadcom BCM57604 NetXtreme-E 25Gb/50Gb/100Gb/200Gb Ethernet"), + PVID(BROADCOM_VENDOR_ID, BCM57602, + "Broadcom BCM57602 NetXtreme-E 25Gb/50Gb Ethernet"), + PVID(BROADCOM_VENDOR_ID, BCM57601, + "Broadcom BCM57601 NetXtreme-E 25Gb/50Gb Ethernet"), PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF1, "Broadcom NetXtreme-C Ethernet Virtual Function"), PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF2, @@ -160,6 +179,8 @@ static const pci_vendor_info_t bnxt_vendor_info_array[] = SLIST_HEAD(softc_list, bnxt_softc_list) pf_list; int bnxt_num_pfs = 0; +void +process_nq(struct bnxt_softc *softc, uint16_t nqid); static void *bnxt_register(device_t dev); /* Soft queue setup and teardown */ @@ -216,7 +237,7 @@ static void bnxt_clear_ids(struct bnxt_softc *softc); static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); -static void bnxt_def_cp_task(void *context); +static void bnxt_def_cp_task(void *context, int pending); static void bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl); static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); @@ -225,7 +246,12 @@ static int bnxt_wol_config(if_ctx_t ctx); static bool bnxt_if_needs_restart(if_ctx_t, enum iflib_restart_event); static int bnxt_i2c_req(if_ctx_t ctx, struct ifi2creq *i2c); static void bnxt_get_port_module_status(struct bnxt_softc *softc); +static void bnxt_rdma_aux_device_init(struct bnxt_softc *softc); +static void bnxt_rdma_aux_device_uninit(struct bnxt_softc *softc); +static void bnxt_queue_fw_reset_work(struct bnxt_softc *bp, unsigned long delay); +void bnxt_queue_sp_work(struct bnxt_softc *bp); +void bnxt_fw_reset(struct bnxt_softc *bp); /* * Device Interface Declaration */ @@ -248,12 +274,38 @@ static driver_t bnxt_driver = { DRIVER_MODULE(bnxt, pci, bnxt_driver, 0, 0); -MODULE_DEPEND(bnxt, pci, 1, 1, 1); -MODULE_DEPEND(bnxt, ether, 1, 1, 1); -MODULE_DEPEND(bnxt, iflib, 1, 1, 1); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DEPEND(if_bnxt, pci, 1, 1, 1); +MODULE_DEPEND(if_bnxt, ether, 1, 1, 1); +MODULE_DEPEND(if_bnxt, iflib, 1, 1, 1); +MODULE_DEPEND(if_bnxt, linuxkpi, 1, 1, 1); +MODULE_VERSION(if_bnxt, 1); IFLIB_PNP_INFO(pci, bnxt, bnxt_vendor_info_array); +void writel_fbsd(struct bnxt_softc *bp, u32, u8, u32); +u32 readl_fbsd(struct bnxt_softc *bp, u32, u8); + +u32 readl_fbsd(struct bnxt_softc *bp, u32 reg_off, u8 bar_idx) +{ + + if (!bar_idx) + return bus_space_read_4(bp->doorbell_bar.tag, bp->doorbell_bar.handle, reg_off); + else + return bus_space_read_4(bp->hwrm_bar.tag, bp->hwrm_bar.handle, reg_off); +} + +void writel_fbsd(struct bnxt_softc *bp, u32 reg_off, u8 bar_idx, u32 val) +{ + + if (!bar_idx) + bus_space_write_4(bp->doorbell_bar.tag, bp->doorbell_bar.handle, reg_off, htole32(val)); + else + bus_space_write_4(bp->hwrm_bar.tag, bp->hwrm_bar.handle, reg_off, htole32(val)); +} + +static DEFINE_IDA(bnxt_aux_dev_ids); + static device_method_t bnxt_iflib_methods[] = { DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), @@ -303,7 +355,7 @@ static driver_t bnxt_iflib_driver = { * iflib shared context */ -#define BNXT_DRIVER_VERSION "2.20.0.1" +#define BNXT_DRIVER_VERSION "230.0.133.0" const char bnxt_driver_version[] = BNXT_DRIVER_VERSION; extern struct if_txrx bnxt_txrx; static struct if_shared_ctx bnxt_sctx_init = { @@ -331,14 +383,20 @@ static struct if_shared_ctx bnxt_sctx_init = { .isc_ntxd_min = {16, 16, 16}, .isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2, PAGE_SIZE / sizeof(struct tx_bd_short), - PAGE_SIZE / sizeof(struct cmpl_base) * 2}, + /* NQ depth 4096 */ + PAGE_SIZE / sizeof(struct cmpl_base) * 16}, .isc_ntxd_max = {BNXT_MAX_TXD, BNXT_MAX_TXD, BNXT_MAX_TXD}, - .isc_admin_intrcnt = 1, + .isc_admin_intrcnt = BNXT_ROCE_IRQ_COUNT, .isc_vendor_info = bnxt_vendor_info_array, .isc_driver_version = bnxt_driver_version, }; +#define PCI_SUBSYSTEM_ID 0x2e +static struct workqueue_struct *bnxt_pf_wq; + +extern void bnxt_destroy_irq(struct bnxt_softc *softc); + /* * Device Methods */ @@ -369,6 +427,18 @@ bnxt_nq_free(struct bnxt_softc *softc) softc->nq_rings = NULL; } + +static void +bnxt_set_db_mask(struct bnxt_softc *bp, struct bnxt_ring *db, + u32 ring_type) +{ + if (BNXT_CHIP_P7(bp)) { + db->db_epoch_mask = db->db_ring_mask + 1; + db->db_epoch_shift = DBR_EPOCH_SFT - ilog2(db->db_epoch_mask); + + } +} + /* * Device Dependent Configuration Functions */ @@ -384,7 +454,7 @@ bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, softc = iflib_get_softc(ctx); - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { bnxt_nq_alloc(softc, ntxqsets); if (!softc->nq_rings) { device_printf(iflib_get_dev(ctx), @@ -429,28 +499,32 @@ bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, softc->tx_cp_rings[i].ring.idx = i; softc->tx_cp_rings[i].ring.id = (softc->scctx->isc_nrxqsets * 2) + 1 + i; - softc->tx_cp_rings[i].ring.doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5: softc->tx_cp_rings[i].ring.id * 0x80; + softc->tx_cp_rings[i].ring.doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size: softc->tx_cp_rings[i].ring.id * 0x80; softc->tx_cp_rings[i].ring.ring_size = softc->scctx->isc_ntxd[0]; + softc->tx_cp_rings[i].ring.db_ring_mask = + softc->tx_cp_rings[i].ring.ring_size - 1; softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs]; softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs]; + /* Set up the TX ring */ softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; softc->tx_rings[i].softc = softc; softc->tx_rings[i].idx = i; softc->tx_rings[i].id = (softc->scctx->isc_nrxqsets * 2) + 1 + i; - softc->tx_rings[i].doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->tx_rings[i].id * 0x80; + softc->tx_rings[i].doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->tx_rings[i].id * 0x80; softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1]; + softc->tx_rings[i].db_ring_mask = softc->tx_rings[i].ring_size - 1; softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1]; softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1]; bnxt_create_tx_sysctls(softc, i); - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { /* Set up the Notification ring (NQ) */ softc->nq_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; softc->nq_rings[i].ring.phys_id = @@ -458,11 +532,13 @@ bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, softc->nq_rings[i].ring.softc = softc; softc->nq_rings[i].ring.idx = i; softc->nq_rings[i].ring.id = i; - softc->nq_rings[i].ring.doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->nq_rings[i].ring.id * 0x80; + softc->nq_rings[i].ring.doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->nq_rings[i].ring.id * 0x80; softc->nq_rings[i].ring.ring_size = softc->scctx->isc_ntxd[2]; + softc->nq_rings[i].ring.db_ring_mask = softc->nq_rings[i].ring.ring_size - 1; softc->nq_rings[i].ring.vaddr = vaddrs[i * ntxqs + 2]; softc->nq_rings[i].ring.paddr = paddrs[i * ntxqs + 2]; + softc->nq_rings[i].type = Q_TYPE_TX; } } @@ -617,13 +693,16 @@ bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, softc->rx_cp_rings[i].ring.softc = softc; softc->rx_cp_rings[i].ring.idx = i; softc->rx_cp_rings[i].ring.id = i + 1; - softc->rx_cp_rings[i].ring.doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->rx_cp_rings[i].ring.id * 0x80; + softc->rx_cp_rings[i].ring.doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->rx_cp_rings[i].ring.id * 0x80; /* * If this ring overflows, RX stops working. */ softc->rx_cp_rings[i].ring.ring_size = softc->scctx->isc_nrxd[0]; + softc->rx_cp_rings[i].ring.db_ring_mask = + softc->rx_cp_rings[i].ring.ring_size - 1; + softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs]; softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs]; @@ -632,9 +711,11 @@ bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, softc->rx_rings[i].softc = softc; softc->rx_rings[i].idx = i; softc->rx_rings[i].id = i + 1; - softc->rx_rings[i].doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->rx_rings[i].id * 0x80; + softc->rx_rings[i].doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->rx_rings[i].id * 0x80; softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; + softc->rx_rings[i].db_ring_mask = + softc->rx_rings[i].ring_size -1; softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; @@ -648,15 +729,15 @@ bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, "Unable to allocate space for TPA\n"); goto tpa_alloc_fail; } - /* Allocate the AG ring */ softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; softc->ag_rings[i].softc = softc; softc->ag_rings[i].idx = i; softc->ag_rings[i].id = nrxqsets + i + 1; - softc->ag_rings[i].doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->ag_rings[i].id * 0x80; + softc->ag_rings[i].doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->ag_rings[i].id * 0x80; softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; + softc->ag_rings[i].db_ring_mask = softc->ag_rings[i].ring_size - 1; softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; @@ -770,26 +851,43 @@ static int bnxt_alloc_hwrm_short_cmd_req(struct bnxt_softc *softc) return rc; } -static void bnxt_free_ring(struct bnxt_softc *bp, struct bnxt_ring_mem_info *rmem) +static void bnxt_free_ring(struct bnxt_softc *softc, struct bnxt_ring_mem_info *rmem) { - int i; + int i; - for (i = 0; i < rmem->nr_pages; i++) { - if (!rmem->pg_arr[i].idi_vaddr) - continue; + for (i = 0; i < rmem->nr_pages; i++) { + if (!rmem->pg_arr[i].idi_vaddr) + continue; iflib_dma_free(&rmem->pg_arr[i]); - rmem->pg_arr[i].idi_vaddr = NULL; - } - if (rmem->pg_tbl.idi_vaddr) { + rmem->pg_arr[i].idi_vaddr = NULL; + } + if (rmem->pg_tbl.idi_vaddr) { iflib_dma_free(&rmem->pg_tbl); - rmem->pg_tbl.idi_vaddr = NULL; + rmem->pg_tbl.idi_vaddr = NULL; + + } + if (rmem->vmem_size && *rmem->vmem) { + free(*rmem->vmem, M_DEVBUF); + *rmem->vmem = NULL; + } +} + +static void bnxt_init_ctx_mem(struct bnxt_ctx_mem_type *ctxm, void *p, int len) +{ + u8 init_val = ctxm->init_value; + u16 offset = ctxm->init_offset; + u8 *p2 = p; + int i; - } - if (rmem->vmem_size && *rmem->vmem) { - free(*rmem->vmem, M_DEVBUF); - *rmem->vmem = NULL; - } + if (!init_val) + return; + if (offset == BNXT_CTX_INIT_INVALID_OFFSET) { + memset(p, init_val, len); + return; + } + for (i = 0; i < len; i += ctxm->entry_size) + *(p2 + i + offset) = init_val; } static int bnxt_alloc_ring(struct bnxt_softc *softc, struct bnxt_ring_mem_info *rmem) @@ -820,8 +918,9 @@ static int bnxt_alloc_ring(struct bnxt_softc *softc, struct bnxt_ring_mem_info * if (rc) return -ENOMEM; - if (rmem->init_val) - memset(rmem->pg_arr[i].idi_vaddr, rmem->init_val, rmem->page_size); + if (rmem->ctx_mem) + bnxt_init_ctx_mem(rmem->ctx_mem, rmem->pg_arr[i].idi_vaddr, + rmem->page_size); if (rmem->nr_pages > 1 || rmem->depth > 0) { if (i == rmem->nr_pages - 2 && @@ -844,11 +943,12 @@ static int bnxt_alloc_ring(struct bnxt_softc *softc, struct bnxt_ring_mem_info * return 0; } -#define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES \ + +#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_SRQ | \ HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ | \ - HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC | \ + HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC | \ HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) static int bnxt_alloc_ctx_mem_blk(struct bnxt_softc *softc, @@ -866,14 +966,14 @@ static int bnxt_alloc_ctx_mem_blk(struct bnxt_softc *softc, } static int bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc, - struct bnxt_ctx_pg_info *ctx_pg, uint32_t mem_size, - uint8_t depth, bool use_init_val) + struct bnxt_ctx_pg_info *ctx_pg, u32 mem_size, + u8 depth, struct bnxt_ctx_mem_type *ctxm) { struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem; int rc; if (!mem_size) - return 0; + return -EINVAL; ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) { @@ -884,8 +984,8 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc, int nr_tbls, i; rmem->depth = 2; - ctx_pg->ctx_pg_tbl = malloc(MAX_CTX_PAGES * sizeof(ctx_pg), - M_DEVBUF, M_NOWAIT | M_ZERO); + ctx_pg->ctx_pg_tbl = kzalloc(MAX_CTX_PAGES * sizeof(ctx_pg), + GFP_KERNEL); if (!ctx_pg->ctx_pg_tbl) return -ENOMEM; nr_tbls = DIV_ROUND_UP(ctx_pg->nr_pages, MAX_CTX_PAGES); @@ -896,7 +996,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc, for (i = 0; i < nr_tbls; i++) { struct bnxt_ctx_pg_info *pg_tbl; - pg_tbl = malloc(sizeof(*pg_tbl), M_DEVBUF, M_NOWAIT | M_ZERO); + pg_tbl = kzalloc(sizeof(*pg_tbl), GFP_KERNEL); if (!pg_tbl) return -ENOMEM; ctx_pg->ctx_pg_tbl[i] = pg_tbl; @@ -904,8 +1004,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc, memcpy(&rmem->pg_tbl, &ctx_pg->ctx_arr[i], sizeof(struct iflib_dma_info)); rmem->depth = 1; rmem->nr_pages = MAX_CTX_PAGES; - if (use_init_val) - rmem->init_val = softc->ctx_mem->ctx_kind_initializer; + rmem->ctx_mem = ctxm; if (i == (nr_tbls - 1)) { int rem = ctx_pg->nr_pages % MAX_CTX_PAGES; @@ -920,8 +1019,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc, rmem->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); if (rmem->nr_pages > 1 || depth) rmem->depth = 1; - if (use_init_val) - rmem->init_val = softc->ctx_mem->ctx_kind_initializer; + rmem->ctx_mem = ctxm; rc = bnxt_alloc_ctx_mem_blk(softc, ctx_pg); } return rc; @@ -949,51 +1047,131 @@ static void bnxt_free_ctx_pg_tbls(struct bnxt_softc *softc, free(pg_tbl , M_DEVBUF); ctx_pg->ctx_pg_tbl[i] = NULL; } - free(ctx_pg->ctx_pg_tbl , M_DEVBUF); + kfree(ctx_pg->ctx_pg_tbl); ctx_pg->ctx_pg_tbl = NULL; } bnxt_free_ring(softc, rmem); ctx_pg->nr_pages = 0; } +static int bnxt_setup_ctxm_pg_tbls(struct bnxt_softc *softc, + struct bnxt_ctx_mem_type *ctxm, u32 entries, + u8 pg_lvl) +{ + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + int i, rc = 0, n = 1; + u32 mem_size; + + if (!ctxm->entry_size || !ctx_pg) + return -EINVAL; + if (ctxm->instance_bmap) + n = hweight32(ctxm->instance_bmap); + if (ctxm->entry_multiple) + entries = roundup(entries, ctxm->entry_multiple); + entries = clamp_t(u32, entries, ctxm->min_entries, ctxm->max_entries); + mem_size = entries * ctxm->entry_size; + for (i = 0; i < n && !rc; i++) { + ctx_pg[i].entries = entries; + rc = bnxt_alloc_ctx_pg_tbls(softc, &ctx_pg[i], mem_size, pg_lvl, + ctxm->init_value ? ctxm : NULL); + } + if (!rc) + ctxm->mem_valid = 1; + return rc; +} + static void bnxt_free_ctx_mem(struct bnxt_softc *softc) { struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; - int i; + u16 type; if (!ctx) return; - if (ctx->tqm_mem[0]) { - for (i = 0; i < softc->max_q + 1; i++) { - if (!ctx->tqm_mem[i]) - continue; - bnxt_free_ctx_pg_tbls(softc, ctx->tqm_mem[i]); - } - free(ctx->tqm_mem[0] , M_DEVBUF); - ctx->tqm_mem[0] = NULL; + for (type = 0; type < BNXT_CTX_MAX; type++) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + int i, n = 1; + + if (!ctx_pg) + continue; + if (ctxm->instance_bmap) + n = hweight32(ctxm->instance_bmap); + for (i = 0; i < n; i++) + bnxt_free_ctx_pg_tbls(softc, &ctx_pg[i]); + + kfree(ctx_pg); + ctxm->pg_info = NULL; } - bnxt_free_ctx_pg_tbls(softc, &ctx->tim_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->mrav_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->stat_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->vnic_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->cq_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->srq_mem); - bnxt_free_ctx_pg_tbls(softc, &ctx->qp_mem); ctx->flags &= ~BNXT_CTX_FLAG_INITED; - free(softc->ctx_mem, M_DEVBUF); + kfree(ctx); softc->ctx_mem = NULL; } +static int +bnxt_backing_store_cfg_v2(struct bnxt_softc *softc, u32 ena) +{ + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + struct bnxt_ctx_mem_type *ctxm; + u16 last_type = BNXT_CTX_INV; + int rc = 0; + u16 type; + + if (BNXT_PF(softc)) { + for (type = BNXT_CTX_SRT_TRACE; type <= BNXT_CTX_ROCE_HWRM_TRACE; type++) { + ctxm = &ctx->ctx_arr[type]; + if (!(ctxm->flags & BNXT_CTX_MEM_TYPE_VALID)) + continue; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, ctxm->max_entries, 1); + if (rc) { + device_printf(softc->dev, "Unable to setup ctx page for type:0x%x.\n", type); + rc = 0; + continue; + } + /* ckp TODO: this is trace buffer related stuff, so keeping it diabled now. needs revisit */ + //bnxt_bs_trace_init(bp, ctxm, type - BNXT_CTX_SRT_TRACE); + last_type = type; + } + } + + if (last_type == BNXT_CTX_INV) { + if (!ena) + return 0; + else if (ena & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) + last_type = BNXT_CTX_MAX - 1; + else + last_type = BNXT_CTX_L2_MAX - 1; + } + ctx->ctx_arr[last_type].last = 1; + + for (type = 0 ; type < BNXT_CTX_V2_MAX; type++) { + ctxm = &ctx->ctx_arr[type]; + + if (!ctxm->mem_valid) + continue; + rc = bnxt_hwrm_func_backing_store_cfg_v2(softc, ctxm, ctxm->last); + if (rc) + return rc; + } + return 0; +} + static int bnxt_alloc_ctx_mem(struct bnxt_softc *softc) { struct bnxt_ctx_pg_info *ctx_pg; + struct bnxt_ctx_mem_type *ctxm; struct bnxt_ctx_mem_info *ctx; - uint32_t mem_size, ena, entries; + u32 l2_qps, qp1_qps, max_qps; + u32 ena, entries_sp, entries; + u32 srqs, max_srqs, min; + u32 num_mr, num_ah; + u32 extra_srqs = 0; + u32 extra_qps = 0; + u8 pg_lvl = 1; int i, rc; - if (!BNXT_CHIP_P5(softc)) + if (!BNXT_CHIP_P5_PLUS(softc)) return 0; rc = bnxt_hwrm_func_backing_store_qcaps(softc); @@ -1006,97 +1184,115 @@ static int bnxt_alloc_ctx_mem(struct bnxt_softc *softc) if (!ctx || (ctx->flags & BNXT_CTX_FLAG_INITED)) return 0; - ctx_pg = &ctx->qp_mem; - ctx_pg->entries = ctx->qp_min_qp1_entries + ctx->qp_max_l2_entries + - (1024 * 64); /* FIXME: Enable 64K QPs */ - mem_size = ctx->qp_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, true); + ena = 0; + if (BNXT_VF(softc)) + goto skip_legacy; + + ctxm = &ctx->ctx_arr[BNXT_CTX_QP]; + l2_qps = ctxm->qp_l2_entries; + qp1_qps = ctxm->qp_qp1_entries; + max_qps = ctxm->max_entries; + ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ]; + srqs = ctxm->srq_l2_entries; + max_srqs = ctxm->max_entries; + if (softc->flags & BNXT_FLAG_ROCE_CAP) { + pg_lvl = 2; + extra_qps = min_t(u32, 65536, max_qps - l2_qps - qp1_qps); + extra_srqs = min_t(u32, 8192, max_srqs - srqs); + } + + ctxm = &ctx->ctx_arr[BNXT_CTX_QP]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, l2_qps + qp1_qps + extra_qps, + pg_lvl); if (rc) return rc; - ctx_pg = &ctx->srq_mem; - /* FIXME: Temporarily enable 8K RoCE SRQs */ - ctx_pg->entries = ctx->srq_max_l2_entries + (1024 * 8); - mem_size = ctx->srq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, true); + ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, srqs + extra_srqs, pg_lvl); if (rc) return rc; - ctx_pg = &ctx->cq_mem; - /* FIXME: Temporarily enable 64K RoCE CQ */ - ctx_pg->entries = ctx->cq_max_l2_entries + (1024 * 64 * 2); - mem_size = ctx->cq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, true); + ctxm = &ctx->ctx_arr[BNXT_CTX_CQ]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, ctxm->cq_l2_entries + + extra_qps * 2, pg_lvl); if (rc) return rc; - ctx_pg = &ctx->vnic_mem; - ctx_pg->entries = ctx->vnic_max_vnic_entries + - ctx->vnic_max_ring_table_entries; - mem_size = ctx->vnic_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 1, true); + ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, ctxm->max_entries, 1); if (rc) return rc; - ctx_pg = &ctx->stat_mem; - ctx_pg->entries = ctx->stat_max_entries; - mem_size = ctx->stat_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 1, true); + ctxm = &ctx->ctx_arr[BNXT_CTX_STAT]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, ctxm->max_entries, 1); if (rc) return rc; - ctx_pg = &ctx->mrav_mem; - /* FIXME: Temporarily enable 256K RoCE MRs */ - ctx_pg->entries = 1024 * 256; - mem_size = ctx->mrav_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, true); + if (!(softc->flags & BNXT_FLAG_ROCE_CAP)) + goto skip_rdma; + + ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV]; + ctx_pg = ctxm->pg_info; + /* 128K extra is needed to accomodate static AH context + * allocation by f/w. + */ + num_mr = min_t(u32, ctxm->max_entries / 2, 1024 * 256); + num_ah = min_t(u32, num_mr, 1024 * 128); + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, num_mr + num_ah, 2); if (rc) return rc; + ctx_pg->entries = num_mr + num_ah; ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV; + if (ctxm->mrav_num_entries_units) + ctx_pg->entries = + ((num_mr / ctxm->mrav_num_entries_units) << 16) | + (num_ah / ctxm->mrav_num_entries_units); - ctx_pg = &ctx->tim_mem; - /* Firmware needs number of TIM entries equal to - * number of Total QP contexts enabled, including - * L2 QPs. - */ - ctx_pg->entries = ctx->qp_min_qp1_entries + - ctx->qp_max_l2_entries + 1024 * 64; - /* FIXME: L2 driver is not able to create queue depth - * worth of 1M 32bit timers. Need a fix when l2-roce - * interface is well designed. - */ - mem_size = ctx->tim_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, false); + ctxm = &ctx->ctx_arr[BNXT_CTX_TIM]; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, l2_qps + qp1_qps + extra_qps, 1); if (rc) return rc; ena |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM; - /* FIXME: Temporarily increase the TQM queue depth - * by 1K for 1K RoCE QPs. - */ - entries = ctx->qp_max_l2_entries + 1024 * 64; - entries = roundup(entries, ctx->tqm_entries_multiple); - entries = clamp_t(uint32_t, entries, ctx->tqm_min_entries_per_ring, - ctx->tqm_max_entries_per_ring); - for (i = 0; i < softc->max_q + 1; i++) { - ctx_pg = ctx->tqm_mem[i]; - ctx_pg->entries = entries; - mem_size = ctx->tqm_entry_size * entries; - rc = bnxt_alloc_ctx_pg_tbls(softc, ctx_pg, mem_size, 2, false); +skip_rdma: + ctxm = &ctx->ctx_arr[BNXT_CTX_STQM]; + min = ctxm->min_entries; + entries_sp = ctx->ctx_arr[BNXT_CTX_VNIC].vnic_entries + l2_qps + + 2 * (extra_qps + qp1_qps) + min; + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, entries_sp, 2); if (rc) return rc; - ena |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP << i; + + ctxm = &ctx->ctx_arr[BNXT_CTX_FTQM]; + entries = l2_qps + 2 * (extra_qps + qp1_qps); + rc = bnxt_setup_ctxm_pg_tbls(softc, ctxm, entries, 2); + if (rc) + return rc; + for (i = 0; i < ctx->tqm_fp_rings_count + 1; i++) { + if (i < BNXT_MAX_TQM_LEGACY_RINGS) + ena |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP << i; + else + ena |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_RING8; } ena |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES; - rc = bnxt_hwrm_func_backing_store_cfg(softc, ena); - if (rc) + +skip_legacy: + if (BNXT_CHIP_P7(softc)) { + if (softc->fw_cap & BNXT_FW_CAP_BACKING_STORE_V2) + rc = bnxt_backing_store_cfg_v2(softc, ena); + } else { + rc = bnxt_hwrm_func_backing_store_cfg(softc, ena); + } + if (rc) { device_printf(softc->dev, "Failed configuring context mem, rc = %d.\n", - rc); - else - ctx->flags |= BNXT_CTX_FLAG_INITED; + rc); + return rc; + } + ctx->flags |= BNXT_CTX_FLAG_INITED; return 0; } + /* * If we update the index, a write barrier is needed after the write to ensure * the completion ring has space before the RX/TX ring does. Since we can't @@ -1239,6 +1435,141 @@ static void bnxt_thor_db_nq(void *db_ptr, bool enable_irq) BUS_SPACE_BARRIER_WRITE); } +static void +bnxt_thor2_db_rx(void *db_ptr, uint16_t idx) +{ + struct bnxt_ring *ring = (struct bnxt_ring *) db_ptr; + struct bnxt_bar_info *db_bar = &ring->softc->doorbell_bar; + uint64_t db_val; + + if (idx >= ring->ring_size) { + device_printf(ring->softc->dev, "%s: BRCM DBG: idx: %d crossed boundary\n", __func__, idx); + return; + } + + db_val = ((DBR_PATH_L2 | DBR_TYPE_SRQ | DBR_VALID | idx) | + ((uint64_t)ring->phys_id << DBR_XID_SFT)); + + /* Add the PI index */ + db_val |= DB_RING_IDX(ring, idx, ring->epoch_arr[idx]); + + bus_space_barrier(db_bar->tag, db_bar->handle, ring->doorbell, 8, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_8(db_bar->tag, db_bar->handle, ring->doorbell, + htole64(db_val)); +} + +static void +bnxt_thor2_db_tx(void *db_ptr, uint16_t idx) +{ + struct bnxt_ring *ring = (struct bnxt_ring *) db_ptr; + struct bnxt_bar_info *db_bar = &ring->softc->doorbell_bar; + uint64_t db_val; + + if (idx >= ring->ring_size) { + device_printf(ring->softc->dev, "%s: BRCM DBG: idx: %d crossed boundary\n", __func__, idx); + return; + } + + db_val = ((DBR_PATH_L2 | DBR_TYPE_SQ | DBR_VALID | idx) | + ((uint64_t)ring->phys_id << DBR_XID_SFT)); + + /* Add the PI index */ + db_val |= DB_RING_IDX(ring, idx, ring->epoch_arr[idx]); + + bus_space_barrier(db_bar->tag, db_bar->handle, ring->doorbell, 8, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_8(db_bar->tag, db_bar->handle, ring->doorbell, + htole64(db_val)); +} + +static void +bnxt_thor2_db_rx_cq(void *db_ptr, bool enable_irq) +{ + struct bnxt_cp_ring *cpr = (struct bnxt_cp_ring *) db_ptr; + struct bnxt_bar_info *db_bar = &cpr->ring.softc->doorbell_bar; + u64 db_msg = { 0 }; + uint32_t cons = cpr->raw_cons; + uint32_t toggle = 0; + + if (cons == UINT32_MAX) + cons = 0; + + if (enable_irq == true) + toggle = cpr->toggle; + + db_msg = DBR_PATH_L2 | ((u64)cpr->ring.phys_id << DBR_XID_SFT) | DBR_VALID | + DB_RING_IDX_CMP(&cpr->ring, cons) | DB_TOGGLE(toggle); + + if (enable_irq) + db_msg |= DBR_TYPE_CQ_ARMALL; + else + db_msg |= DBR_TYPE_CQ; + + bus_space_barrier(db_bar->tag, db_bar->handle, cpr->ring.doorbell, 8, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_8(db_bar->tag, db_bar->handle, cpr->ring.doorbell, + htole64(*(uint64_t *)&db_msg)); + bus_space_barrier(db_bar->tag, db_bar->handle, 0, db_bar->size, + BUS_SPACE_BARRIER_WRITE); +} + +static void +bnxt_thor2_db_tx_cq(void *db_ptr, bool enable_irq) +{ + struct bnxt_cp_ring *cpr = (struct bnxt_cp_ring *) db_ptr; + struct bnxt_bar_info *db_bar = &cpr->ring.softc->doorbell_bar; + u64 db_msg = { 0 }; + uint32_t cons = cpr->raw_cons; + uint32_t toggle = 0; + + if (enable_irq == true) + toggle = cpr->toggle; + + db_msg = DBR_PATH_L2 | ((u64)cpr->ring.phys_id << DBR_XID_SFT) | DBR_VALID | + DB_RING_IDX_CMP(&cpr->ring, cons) | DB_TOGGLE(toggle); + + if (enable_irq) + db_msg |= DBR_TYPE_CQ_ARMALL; + else + db_msg |= DBR_TYPE_CQ; + + bus_space_barrier(db_bar->tag, db_bar->handle, cpr->ring.doorbell, 8, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_8(db_bar->tag, db_bar->handle, cpr->ring.doorbell, + htole64(*(uint64_t *)&db_msg)); + bus_space_barrier(db_bar->tag, db_bar->handle, 0, db_bar->size, + BUS_SPACE_BARRIER_WRITE); +} + +static void +bnxt_thor2_db_nq(void *db_ptr, bool enable_irq) +{ + struct bnxt_cp_ring *cpr = (struct bnxt_cp_ring *) db_ptr; + struct bnxt_bar_info *db_bar = &cpr->ring.softc->doorbell_bar; + u64 db_msg = { 0 }; + uint32_t cons = cpr->raw_cons; + uint32_t toggle = 0; + + if (enable_irq == true) + toggle = cpr->toggle; + + db_msg = DBR_PATH_L2 | ((u64)cpr->ring.phys_id << DBR_XID_SFT) | DBR_VALID | + DB_RING_IDX_CMP(&cpr->ring, cons) | DB_TOGGLE(toggle); + + if (enable_irq) + db_msg |= DBR_TYPE_NQ_ARM; + else + db_msg |= DBR_TYPE_NQ_MASK; + + bus_space_barrier(db_bar->tag, db_bar->handle, cpr->ring.doorbell, 8, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_8(db_bar->tag, db_bar->handle, cpr->ring.doorbell, + htole64(*(uint64_t *)&db_msg)); + bus_space_barrier(db_bar->tag, db_bar->handle, 0, db_bar->size, + BUS_SPACE_BARRIER_WRITE); +} + struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, char *dev_name) { struct bnxt_softc_list *sc = NULL; @@ -1261,6 +1592,702 @@ struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, return NULL; } + +static void bnxt_verify_asym_queues(struct bnxt_softc *softc) +{ + uint8_t i, lltc = 0; + + if (!softc->max_lltc) + return; + + /* Verify that lossless TX and RX queues are in the same index */ + for (i = 0; i < softc->max_tc; i++) { + if (BNXT_LLQ(softc->tx_q_info[i].queue_profile) && + BNXT_LLQ(softc->rx_q_info[i].queue_profile)) + lltc++; + } + softc->max_lltc = min(softc->max_lltc, lltc); +} + +static int bnxt_hwrm_poll(struct bnxt_softc *bp) +{ + struct hwrm_ver_get_output *resp = + (void *)bp->hwrm_cmd_resp.idi_vaddr; + struct hwrm_ver_get_input req = {0}; + int rc; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET); + + req.hwrm_intf_maj = HWRM_VERSION_MAJOR; + req.hwrm_intf_min = HWRM_VERSION_MINOR; + req.hwrm_intf_upd = HWRM_VERSION_UPDATE; + + rc = _hwrm_send_message(bp, &req, sizeof(req)); + if (rc) + return rc; + + if (resp->flags & HWRM_VER_GET_OUTPUT_FLAGS_DEV_NOT_RDY) + rc = -EAGAIN; + + return rc; +} + +static void bnxt_rtnl_lock_sp(struct bnxt_softc *bp) +{ + /* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK + * set. If the device is being closed, bnxt_close() may be holding + * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear. So we + * must clear BNXT_STATE_IN_SP_TASK before holding rtnl(). + */ + clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); + rtnl_lock(); +} + +static void bnxt_rtnl_unlock_sp(struct bnxt_softc *bp) +{ + set_bit(BNXT_STATE_IN_SP_TASK, &bp->state); + rtnl_unlock(); +} + +static void bnxt_fw_fatal_close(struct bnxt_softc *softc) +{ + bnxt_disable_intr(softc->ctx); + if (pci_is_enabled(softc->pdev)) + pci_disable_device(softc->pdev); +} + +static u32 bnxt_fw_health_readl(struct bnxt_softc *bp, int reg_idx) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + u32 reg = fw_health->regs[reg_idx]; + u32 reg_type, reg_off, val = 0; + + reg_type = BNXT_FW_HEALTH_REG_TYPE(reg); + reg_off = BNXT_FW_HEALTH_REG_OFF(reg); + switch (reg_type) { + case BNXT_FW_HEALTH_REG_TYPE_CFG: + pci_read_config_dword(bp->pdev, reg_off, &val); + break; + case BNXT_FW_HEALTH_REG_TYPE_GRC: + reg_off = fw_health->mapped_regs[reg_idx]; + fallthrough; + case BNXT_FW_HEALTH_REG_TYPE_BAR0: + val = readl_fbsd(bp, reg_off, 0); + break; + case BNXT_FW_HEALTH_REG_TYPE_BAR1: + val = readl_fbsd(bp, reg_off, 2); + break; + } + if (reg_idx == BNXT_FW_RESET_INPROG_REG) + val &= fw_health->fw_reset_inprog_reg_mask; + return val; +} + +static void bnxt_fw_reset_close(struct bnxt_softc *bp) +{ + int i; + bnxt_ulp_stop(bp); + /* When firmware is in fatal state, quiesce device and disable + * bus master to prevent any potential bad DMAs before freeing + * kernel memory. + */ + if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) { + u16 val = 0; + + val = pci_read_config(bp->dev, PCI_SUBSYSTEM_ID, 2); + if (val == 0xffff) { + bp->fw_reset_min_dsecs = 0; + } + bnxt_fw_fatal_close(bp); + } + + iflib_request_reset(bp->ctx); + bnxt_stop(bp->ctx); + bnxt_hwrm_func_drv_unrgtr(bp, false); + + for (i = bp->nrxqsets-1; i>=0; i--) { + if (BNXT_CHIP_P5_PLUS(bp)) + iflib_irq_free(bp->ctx, &bp->nq_rings[i].irq); + else + iflib_irq_free(bp->ctx, &bp->rx_cp_rings[i].irq); + + } + if (pci_is_enabled(bp->pdev)) + pci_disable_device(bp->pdev); + pci_disable_busmaster(bp->dev); + bnxt_free_ctx_mem(bp); +} + +static bool is_bnxt_fw_ok(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + bool no_heartbeat = false, has_reset = false; + u32 val; + + val = bnxt_fw_health_readl(bp, BNXT_FW_HEARTBEAT_REG); + if (val == fw_health->last_fw_heartbeat) + no_heartbeat = true; + + val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG); + if (val != fw_health->last_fw_reset_cnt) + has_reset = true; + + if (!no_heartbeat && has_reset) + return true; + + return false; +} + +void bnxt_fw_reset(struct bnxt_softc *bp) +{ + bnxt_rtnl_lock_sp(bp); + if (test_bit(BNXT_STATE_OPEN, &bp->state) && + !test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { + int tmo; + set_bit(BNXT_STATE_IN_FW_RESET, &bp->state); + bnxt_fw_reset_close(bp); + + if ((bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD)) { + bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW_DOWN; + tmo = HZ / 10; + } else { + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + tmo = bp->fw_reset_min_dsecs * HZ /10; + } + bnxt_queue_fw_reset_work(bp, tmo); + } + bnxt_rtnl_unlock_sp(bp); +} + +static void bnxt_queue_fw_reset_work(struct bnxt_softc *bp, unsigned long delay) +{ + if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))) + return; + + if (BNXT_PF(bp)) + queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay); + else + schedule_delayed_work(&bp->fw_reset_task, delay); +} + +void bnxt_queue_sp_work(struct bnxt_softc *bp) +{ + if (BNXT_PF(bp)) + queue_work(bnxt_pf_wq, &bp->sp_task); + else + schedule_work(&bp->sp_task); +} + +static void bnxt_fw_reset_writel(struct bnxt_softc *bp, int reg_idx) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + u32 reg = fw_health->fw_reset_seq_regs[reg_idx]; + u32 val = fw_health->fw_reset_seq_vals[reg_idx]; + u32 reg_type, reg_off, delay_msecs; + + delay_msecs = fw_health->fw_reset_seq_delay_msec[reg_idx]; + reg_type = BNXT_FW_HEALTH_REG_TYPE(reg); + reg_off = BNXT_FW_HEALTH_REG_OFF(reg); + switch (reg_type) { + case BNXT_FW_HEALTH_REG_TYPE_CFG: + pci_write_config_dword(bp->pdev, reg_off, val); + break; + case BNXT_FW_HEALTH_REG_TYPE_GRC: + writel_fbsd(bp, BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4, 0, reg_off & BNXT_GRC_BASE_MASK); + reg_off = (reg_off & BNXT_GRC_OFFSET_MASK) + 0x2000; + fallthrough; + case BNXT_FW_HEALTH_REG_TYPE_BAR0: + writel_fbsd(bp, reg_off, 0, val); + break; + case BNXT_FW_HEALTH_REG_TYPE_BAR1: + writel_fbsd(bp, reg_off, 2, val); + break; + } + if (delay_msecs) { + pci_read_config_dword(bp->pdev, 0, &val); + msleep(delay_msecs); + } +} + +static void bnxt_reset_all(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + int i, rc; + + if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) { + bp->fw_reset_timestamp = jiffies; + return; + } + + if (fw_health->flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_HOST) { + for (i = 0; i < fw_health->fw_reset_seq_cnt; i++) + bnxt_fw_reset_writel(bp, i); + } else if (fw_health->flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_CO_CPU) { + struct hwrm_fw_reset_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FW_RESET); + req.target_id = htole16(HWRM_TARGET_ID_KONG); + req.embedded_proc_type = HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_CHIP; + req.selfrst_status = HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTASAP; + req.flags = HWRM_FW_RESET_INPUT_FLAGS_RESET_GRACEFUL; + rc = hwrm_send_message(bp, &req, sizeof(req)); + + if (rc != -ENODEV) + device_printf(bp->dev, "Unable to reset FW rc=%d\n", rc); + } + bp->fw_reset_timestamp = jiffies; +} + +static int __bnxt_alloc_fw_health(struct bnxt_softc *bp) +{ + if (bp->fw_health) + return 0; + + bp->fw_health = kzalloc(sizeof(*bp->fw_health), GFP_KERNEL); + if (!bp->fw_health) + return -ENOMEM; + + mutex_init(&bp->fw_health->lock); + return 0; +} + +static int bnxt_alloc_fw_health(struct bnxt_softc *bp) +{ + int rc; + + if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) && + !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) + return 0; + + rc = __bnxt_alloc_fw_health(bp); + if (rc) { + bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET; + bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; + return rc; + } + + return 0; +} + +static inline void __bnxt_map_fw_health_reg(struct bnxt_softc *bp, u32 reg) +{ + writel_fbsd(bp, BNXT_GRCPF_REG_WINDOW_BASE_OUT + BNXT_FW_HEALTH_WIN_MAP_OFF, 0, reg & BNXT_GRC_BASE_MASK); +} + +static int bnxt_map_fw_health_regs(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + u32 reg_base = 0xffffffff; + int i; + + bp->fw_health->status_reliable = false; + bp->fw_health->resets_reliable = false; + /* Only pre-map the monitoring GRC registers using window 3 */ + for (i = 0; i < 4; i++) { + u32 reg = fw_health->regs[i]; + + if (BNXT_FW_HEALTH_REG_TYPE(reg) != BNXT_FW_HEALTH_REG_TYPE_GRC) + continue; + if (reg_base == 0xffffffff) + reg_base = reg & BNXT_GRC_BASE_MASK; + if ((reg & BNXT_GRC_BASE_MASK) != reg_base) + return -ERANGE; + fw_health->mapped_regs[i] = BNXT_FW_HEALTH_WIN_OFF(reg); + } + bp->fw_health->status_reliable = true; + bp->fw_health->resets_reliable = true; + if (reg_base == 0xffffffff) + return 0; + + __bnxt_map_fw_health_reg(bp, reg_base); + return 0; +} + +static void bnxt_inv_fw_health_reg(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + u32 reg_type; + + if (!fw_health) + return; + + reg_type = BNXT_FW_HEALTH_REG_TYPE(fw_health->regs[BNXT_FW_HEALTH_REG]); + if (reg_type == BNXT_FW_HEALTH_REG_TYPE_GRC) + fw_health->status_reliable = false; + + reg_type = BNXT_FW_HEALTH_REG_TYPE(fw_health->regs[BNXT_FW_RESET_CNT_REG]); + if (reg_type == BNXT_FW_HEALTH_REG_TYPE_GRC) + fw_health->resets_reliable = false; +} + +static int bnxt_hwrm_error_recovery_qcfg(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + struct hwrm_error_recovery_qcfg_output *resp = + (void *)bp->hwrm_cmd_resp.idi_vaddr; + struct hwrm_error_recovery_qcfg_input req = {0}; + int rc, i; + + if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_ERROR_RECOVERY_QCFG); + rc = _hwrm_send_message(bp, &req, sizeof(req)); + + if (rc) + goto err_recovery_out; + fw_health->flags = le32toh(resp->flags); + if ((fw_health->flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_CO_CPU) && + !(bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL)) { + rc = -EINVAL; + goto err_recovery_out; + } + fw_health->polling_dsecs = le32toh(resp->driver_polling_freq); + fw_health->master_func_wait_dsecs = + le32toh(resp->master_func_wait_period); + fw_health->normal_func_wait_dsecs = + le32toh(resp->normal_func_wait_period); + fw_health->post_reset_wait_dsecs = + le32toh(resp->master_func_wait_period_after_reset); + fw_health->post_reset_max_wait_dsecs = + le32toh(resp->max_bailout_time_after_reset); + fw_health->regs[BNXT_FW_HEALTH_REG] = + le32toh(resp->fw_health_status_reg); + fw_health->regs[BNXT_FW_HEARTBEAT_REG] = + le32toh(resp->fw_heartbeat_reg); + fw_health->regs[BNXT_FW_RESET_CNT_REG] = + le32toh(resp->fw_reset_cnt_reg); + fw_health->regs[BNXT_FW_RESET_INPROG_REG] = + le32toh(resp->reset_inprogress_reg); + fw_health->fw_reset_inprog_reg_mask = + le32toh(resp->reset_inprogress_reg_mask); + fw_health->fw_reset_seq_cnt = resp->reg_array_cnt; + if (fw_health->fw_reset_seq_cnt >= 16) { + rc = -EINVAL; + goto err_recovery_out; + } + for (i = 0; i < fw_health->fw_reset_seq_cnt; i++) { + fw_health->fw_reset_seq_regs[i] = + le32toh(resp->reset_reg[i]); + fw_health->fw_reset_seq_vals[i] = + le32toh(resp->reset_reg_val[i]); + fw_health->fw_reset_seq_delay_msec[i] = + le32toh(resp->delay_after_reset[i]); + } +err_recovery_out: + if (!rc) + rc = bnxt_map_fw_health_regs(bp); + if (rc) + bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; + return rc; +} + +static int bnxt_drv_rgtr(struct bnxt_softc *bp) +{ + int rc; + + /* determine whether we can support error recovery before + * registering with FW + */ + if (bnxt_alloc_fw_health(bp)) { + device_printf(bp->dev, "no memory for firmware error recovery\n"); + } else { + rc = bnxt_hwrm_error_recovery_qcfg(bp); + if (rc) + device_printf(bp->dev, "hwrm query error recovery failure rc: %d\n", + rc); + } + rc = bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, false); //sumit dbg: revisit the params + if (rc) + return -ENODEV; + return 0; +} + +static bool bnxt_fw_reset_timeout(struct bnxt_softc *bp) +{ + return time_after(jiffies, bp->fw_reset_timestamp + + (bp->fw_reset_max_dsecs * HZ / 10)); +} + +static int bnxt_open(struct bnxt_softc *bp) +{ + int rc = 0; + if (BNXT_PF(bp)) + rc = bnxt_hwrm_nvm_get_dev_info(bp, &bp->nvm_info->mfg_id, + &bp->nvm_info->device_id, &bp->nvm_info->sector_size, + &bp->nvm_info->size, &bp->nvm_info->reserved_size, + &bp->nvm_info->available_size); + + /* Get the queue config */ + rc = bnxt_hwrm_queue_qportcfg(bp, HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX); + if (rc) { + device_printf(bp->dev, "reinit: hwrm qportcfg (tx) failed\n"); + return rc; + } + if (bp->is_asym_q) { + rc = bnxt_hwrm_queue_qportcfg(bp, + HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX); + if (rc) { + device_printf(bp->dev, "re-init: hwrm qportcfg (rx) failed\n"); + return rc; + } + bnxt_verify_asym_queues(bp); + } else { + bp->rx_max_q = bp->tx_max_q; + memcpy(bp->rx_q_info, bp->tx_q_info, sizeof(bp->rx_q_info)); + memcpy(bp->rx_q_ids, bp->tx_q_ids, sizeof(bp->rx_q_ids)); + } + /* Get the HW capabilities */ + rc = bnxt_hwrm_func_qcaps(bp); + if (rc) + return rc; + + /* Register the driver with the FW */ + rc = bnxt_drv_rgtr(bp); + if (rc) + return rc; + if (bp->hwrm_spec_code >= 0x10803) { + rc = bnxt_alloc_ctx_mem(bp); + if (rc) { + device_printf(bp->dev, "attach: alloc_ctx_mem failed\n"); + return rc; + } + rc = bnxt_hwrm_func_resc_qcaps(bp, true); + if (!rc) + bp->flags |= BNXT_FLAG_FW_CAP_NEW_RM; + } + + if (BNXT_CHIP_P5_PLUS(bp)) + bnxt_hwrm_reserve_pf_rings(bp); + /* Get the current configuration of this function */ + rc = bnxt_hwrm_func_qcfg(bp); + if (rc) { + device_printf(bp->dev, "re-init: hwrm func qcfg failed\n"); + return rc; + } + + bnxt_msix_intr_assign(bp->ctx, 0); + bnxt_init(bp->ctx); + bnxt_intr_enable(bp->ctx); + + if (test_and_clear_bit(BNXT_STATE_FW_RESET_DET, &bp->state)) { + if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { + bnxt_ulp_start(bp, 0); + } + } + + device_printf(bp->dev, "Network interface is UP and operational\n"); + + return rc; +} +static void bnxt_fw_reset_abort(struct bnxt_softc *bp, int rc) +{ + clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); + if (bp->fw_reset_state != BNXT_FW_RESET_STATE_POLL_VF) { + bnxt_ulp_start(bp, rc); + } + bp->fw_reset_state = 0; +} + +static void bnxt_fw_reset_task(struct work_struct *work) +{ + struct bnxt_softc *bp = container_of(work, struct bnxt_softc, fw_reset_task.work); + int rc = 0; + + if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { + device_printf(bp->dev, "bnxt_fw_reset_task() called when not in fw reset mode!\n"); + return; + } + + switch (bp->fw_reset_state) { + case BNXT_FW_RESET_STATE_POLL_FW_DOWN: { + u32 val; + + val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG); + if (!(val & BNXT_FW_STATUS_SHUTDOWN) && + !bnxt_fw_reset_timeout(bp)) { + bnxt_queue_fw_reset_work(bp, HZ / 5); + return; + } + + if (!bp->fw_health->primary) { + u32 wait_dsecs = bp->fw_health->normal_func_wait_dsecs; + + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); + return; + } + bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW; + } + fallthrough; + case BNXT_FW_RESET_STATE_RESET_FW: + bnxt_reset_all(bp); + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); + return; + case BNXT_FW_RESET_STATE_ENABLE_DEV: + bnxt_inv_fw_health_reg(bp); + if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) && + !bp->fw_reset_min_dsecs) { + u16 val; + + val = pci_read_config(bp->dev, PCI_SUBSYSTEM_ID, 2); + if (val == 0xffff) { + if (bnxt_fw_reset_timeout(bp)) { + device_printf(bp->dev, "Firmware reset aborted, PCI config space invalid\n"); + rc = -ETIMEDOUT; + goto fw_reset_abort; + } + bnxt_queue_fw_reset_work(bp, HZ / 1000); + return; + } + } + clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state); + clear_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state); + if (!pci_is_enabled(bp->pdev)) { + if (pci_enable_device(bp->pdev)) { + device_printf(bp->dev, "Cannot re-enable PCI device\n"); + rc = -ENODEV; + goto fw_reset_abort; + } + } + pci_set_master(bp->pdev); + bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW; + fallthrough; + case BNXT_FW_RESET_STATE_POLL_FW: + bp->hwrm_cmd_timeo = SHORT_HWRM_CMD_TIMEOUT; + rc = bnxt_hwrm_poll(bp); + if (rc) { + if (bnxt_fw_reset_timeout(bp)) { + device_printf(bp->dev, "Firmware reset aborted\n"); + goto fw_reset_abort_status; + } + bnxt_queue_fw_reset_work(bp, HZ / 5); + return; + } + bp->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT; + bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING; + fallthrough; + case BNXT_FW_RESET_STATE_OPENING: + rc = bnxt_open(bp); + if (rc) { + device_printf(bp->dev, "bnxt_open() failed during FW reset\n"); + bnxt_fw_reset_abort(bp, rc); + rtnl_unlock(); + return; + } + + if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && + bp->fw_health->enabled) { + bp->fw_health->last_fw_reset_cnt = + bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG); + } + bp->fw_reset_state = 0; + smp_mb__before_atomic(); + clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); + bnxt_ulp_start(bp, 0); + clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state); + set_bit(BNXT_STATE_OPEN, &bp->state); + rtnl_unlock(); + } + return; + +fw_reset_abort_status: + if (bp->fw_health->status_reliable || + (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) { + u32 sts = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG); + + device_printf(bp->dev, "fw_health_status 0x%x\n", sts); + } +fw_reset_abort: + rtnl_lock(); + bnxt_fw_reset_abort(bp, rc); + rtnl_unlock(); +} + +static void bnxt_force_fw_reset(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + u32 wait_dsecs; + + if (!test_bit(BNXT_STATE_OPEN, &bp->state) || + test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) + return; + bnxt_fw_reset_close(bp); + wait_dsecs = fw_health->master_func_wait_dsecs; + if (fw_health->primary) { + if (fw_health->flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_CO_CPU) + wait_dsecs = 0; + bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW; + } else { + bp->fw_reset_timestamp = jiffies + wait_dsecs * HZ / 10; + wait_dsecs = fw_health->normal_func_wait_dsecs; + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + } + + bp->fw_reset_min_dsecs = fw_health->post_reset_wait_dsecs; + bp->fw_reset_max_dsecs = fw_health->post_reset_max_wait_dsecs; + bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); +} + +static void bnxt_fw_exception(struct bnxt_softc *bp) +{ + device_printf(bp->dev, "Detected firmware fatal condition, initiating reset\n"); + set_bit(BNXT_STATE_FW_FATAL_COND, &bp->state); + bnxt_rtnl_lock_sp(bp); + bnxt_force_fw_reset(bp); + bnxt_rtnl_unlock_sp(bp); +} + +static void __bnxt_fw_recover(struct bnxt_softc *bp) +{ + if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) || + test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state)) + bnxt_fw_reset(bp); + else + bnxt_fw_exception(bp); +} + +static void bnxt_devlink_health_fw_report(struct bnxt_softc *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + + if (!fw_health) + return; + + if (!fw_health->fw_reporter) { + __bnxt_fw_recover(bp); + return; + } +} + +static void bnxt_sp_task(struct work_struct *work) +{ + struct bnxt_softc *bp = container_of(work, struct bnxt_softc, sp_task); + + set_bit(BNXT_STATE_IN_SP_TASK, &bp->state); + smp_mb__after_atomic(); + if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { + clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); + return; + } + + if (test_and_clear_bit(BNXT_FW_RESET_NOTIFY_SP_EVENT, &bp->sp_event)) { + if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) || + test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state)) + bnxt_devlink_health_fw_report(bp); + else + bnxt_fw_reset(bp); + } + + if (test_and_clear_bit(BNXT_FW_EXCEPTION_SP_EVENT, &bp->sp_event)) { + if (!is_bnxt_fw_ok(bp)) + bnxt_devlink_health_fw_report(bp); + } + smp_mb__before_atomic(); + clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); +} + /* Device setup and teardown */ static int bnxt_attach_pre(if_ctx_t ctx) @@ -1288,6 +2315,7 @@ bnxt_attach_pre(if_ctx_t ctx) case BCM57414_NPAR2: case BCM57416_NPAR1: case BCM57416_NPAR2: + case BCM57504_NPAR: softc->flags |= BNXT_FLAG_NPAR; break; case NETXTREME_C_VF1: @@ -1300,7 +2328,6 @@ bnxt_attach_pre(if_ctx_t ctx) break; } -#define PCI_DEVFN(device, func) ((((device) & 0x1f) << 3) | ((func) & 0x07)) softc->domain = pci_get_domain(softc->dev); softc->bus = pci_get_bus(softc->dev); softc->slot = pci_get_slot(softc->dev); @@ -1315,8 +2342,24 @@ bnxt_attach_pre(if_ctx_t ctx) pci_enable_busmaster(softc->dev); - if (bnxt_pci_mapping(softc)) - return (ENXIO); + if (bnxt_pci_mapping(softc)) { + device_printf(softc->dev, "PCI mapping failed\n"); + rc = ENXIO; + goto pci_map_fail; + } + + softc->pdev = kzalloc(sizeof(*softc->pdev), GFP_KERNEL); + if (!softc->pdev) { + device_printf(softc->dev, "pdev alloc failed\n"); + rc = -ENOMEM; + goto free_pci_map; + } + + rc = linux_pci_attach_device(softc->dev, NULL, NULL, softc->pdev); + if (rc) { + device_printf(softc->dev, "Failed to attach Linux PCI device 0x%x\n", rc); + goto pci_attach_fail; + } /* HWRM setup/init */ BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); @@ -1356,22 +2399,37 @@ bnxt_attach_pre(if_ctx_t ctx) if ((softc->ver_info->chip_num == BCM57508) || (softc->ver_info->chip_num == BCM57504) || - (softc->ver_info->chip_num == BCM57502)) + (softc->ver_info->chip_num == BCM57504_NPAR) || + (softc->ver_info->chip_num == BCM57502) || + (softc->ver_info->chip_num == BCM57601) || + (softc->ver_info->chip_num == BCM57602) || + (softc->ver_info->chip_num == BCM57604)) softc->flags |= BNXT_FLAG_CHIP_P5; + if (softc->ver_info->chip_num == BCM57608) + softc->flags |= BNXT_FLAG_CHIP_P7; + softc->flags |= BNXT_FLAG_TPA; - /* No TPA for Thor A0 */ - if (BNXT_CHIP_P5(softc) && (!softc->ver_info->chip_rev) && + if (BNXT_CHIP_P5_PLUS(softc) && (!softc->ver_info->chip_rev) && (!softc->ver_info->chip_metal)) softc->flags &= ~BNXT_FLAG_TPA; - /* TBD ++ Add TPA support from Thor B1 */ - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->flags &= ~BNXT_FLAG_TPA; /* Get NVRAM info */ if (BNXT_PF(softc)) { + if (!bnxt_pf_wq) { + bnxt_pf_wq = + create_singlethread_workqueue("bnxt_pf_wq"); + if (!bnxt_pf_wq) { + device_printf(softc->dev, "Unable to create workqueue.\n"); + rc = -ENOMEM; + goto nvm_alloc_fail; + } + } + softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), M_DEVBUF, M_NOWAIT | M_ZERO); if (softc->nvm_info == NULL) { @@ -1393,6 +2451,12 @@ bnxt_attach_pre(if_ctx_t ctx) softc->db_ops.bnxt_db_rx_cq = bnxt_thor_db_rx_cq; softc->db_ops.bnxt_db_tx_cq = bnxt_thor_db_tx_cq; softc->db_ops.bnxt_db_nq = bnxt_thor_db_nq; + } else if (BNXT_CHIP_P7(softc)) { + softc->db_ops.bnxt_db_tx = bnxt_thor2_db_tx; + softc->db_ops.bnxt_db_rx = bnxt_thor2_db_rx; + softc->db_ops.bnxt_db_rx_cq = bnxt_thor2_db_rx_cq; + softc->db_ops.bnxt_db_tx_cq = bnxt_thor2_db_tx_cq; + softc->db_ops.bnxt_db_nq = bnxt_thor2_db_nq; } else { softc->db_ops.bnxt_db_tx = bnxt_cuw_db_tx; softc->db_ops.bnxt_db_rx = bnxt_cuw_db_rx; @@ -1400,25 +2464,39 @@ bnxt_attach_pre(if_ctx_t ctx) softc->db_ops.bnxt_db_tx_cq = bnxt_cuw_db_cq; } - /* Register the driver with the FW */ - rc = bnxt_hwrm_func_drv_rgtr(softc); - if (rc) { - device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); - goto drv_rgtr_fail; - } - - rc = bnxt_hwrm_func_rgtr_async_events(softc, NULL, 0); - if (rc) { - device_printf(softc->dev, "attach: hwrm rgtr async evts failed\n"); - goto drv_rgtr_fail; - } /* Get the queue config */ - rc = bnxt_hwrm_queue_qportcfg(softc); + rc = bnxt_hwrm_queue_qportcfg(softc, HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX); if (rc) { - device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); + device_printf(softc->dev, "attach: hwrm qportcfg (tx) failed\n"); goto failed; } + if (softc->is_asym_q) { + rc = bnxt_hwrm_queue_qportcfg(softc, + HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX); + if (rc) { + device_printf(softc->dev, "attach: hwrm qportcfg (rx) failed\n"); + return rc; + } + bnxt_verify_asym_queues(softc); + } else { + softc->rx_max_q = softc->tx_max_q; + memcpy(softc->rx_q_info, softc->tx_q_info, sizeof(softc->rx_q_info)); + memcpy(softc->rx_q_ids, softc->tx_q_ids, sizeof(softc->rx_q_ids)); + } + + /* Get the HW capabilities */ + rc = bnxt_hwrm_func_qcaps(softc); + if (rc) + goto failed; + + /* + * Register the driver with the FW + * Register the async events with the FW + */ + rc = bnxt_drv_rgtr(softc); + if (rc) + goto failed; if (softc->hwrm_spec_code >= 0x10803) { rc = bnxt_alloc_ctx_mem(softc); @@ -1431,11 +2509,6 @@ bnxt_attach_pre(if_ctx_t ctx) softc->flags |= BNXT_FLAG_FW_CAP_NEW_RM; } - /* Get the HW capabilities */ - rc = bnxt_hwrm_func_qcaps(softc); - if (rc) - goto failed; - /* Get the current configuration of this function */ rc = bnxt_hwrm_func_qcfg(softc); if (rc) { @@ -1467,7 +2540,7 @@ bnxt_attach_pre(if_ctx_t ctx) /* Get the queue config */ bnxt_get_wol_settings(softc); - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) bnxt_hwrm_reserve_pf_rings(softc); rc = bnxt_hwrm_func_qcfg(softc); if (rc) { @@ -1540,17 +2613,17 @@ bnxt_attach_pre(if_ctx_t ctx) softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; softc->def_cp_ring.ring.softc = softc; softc->def_cp_ring.ring.id = 0; - softc->def_cp_ring.ring.doorbell = (BNXT_CHIP_P5(softc)) ? - DB_PF_OFFSET_P5 : softc->def_cp_ring.ring.id * 0x80; + softc->def_cp_ring.ring.doorbell = (BNXT_CHIP_P5_PLUS(softc)) ? + softc->legacy_db_size : softc->def_cp_ring.ring.id * 0x80; softc->def_cp_ring.ring.ring_size = PAGE_SIZE / sizeof(struct cmpl_base); + softc->def_cp_ring.ring.db_ring_mask = softc->def_cp_ring.ring.ring_size -1 ; rc = iflib_dma_alloc(ctx, sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, &softc->def_cp_ring_mem, 0); softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; - iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, - "dflt_cp"); + iflib_config_task_init(ctx, &softc->def_cp_task, bnxt_def_cp_task); rc = bnxt_init_sysctl_ctx(softc); if (rc) @@ -1581,6 +2654,14 @@ bnxt_attach_pre(if_ctx_t ctx) if (rc) goto failed; + rc = bnxt_create_dcb_sysctls(softc); + if (rc) + goto failed; + + set_bit(BNXT_STATE_OPEN, &softc->state); + INIT_WORK(&softc->sp_task, bnxt_sp_task); + INIT_DELAYED_WORK(&softc->fw_reset_task, bnxt_fw_reset_task); + /* Initialize the vlan list */ SLIST_INIT(&softc->vnic_info.vlan_tags); softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; @@ -1593,7 +2674,6 @@ failed: bnxt_free_sysctl_ctx(softc); init_sysctl_failed: bnxt_hwrm_func_drv_unrgtr(softc, false); -drv_rgtr_fail: if (BNXT_PF(softc)) free(softc->nvm_info, M_DEVBUF); nvm_alloc_fail: @@ -1605,7 +2685,14 @@ ver_alloc_fail: bnxt_free_hwrm_dma_mem(softc); dma_fail: BNXT_HWRM_LOCK_DESTROY(softc); + if (softc->pdev) + linux_pci_detach_device(softc->pdev); +pci_attach_fail: + kfree(softc->pdev); + softc->pdev = NULL; +free_pci_map: bnxt_pci_mapping_free(softc); +pci_map_fail: pci_disable_busmaster(softc->dev); return (rc); } @@ -1617,6 +2704,7 @@ bnxt_attach_post(if_ctx_t ctx) if_t ifp = iflib_get_ifp(ctx); int rc; + softc->ifp = ifp; bnxt_create_config_sysctls_post(softc); /* Update link state etc... */ @@ -1626,6 +2714,7 @@ bnxt_attach_post(if_ctx_t ctx) /* Needs to be done after probing the phy */ bnxt_create_ver_sysctls(softc); + ifmedia_removeall(softc->media); bnxt_add_media_types(softc); ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); @@ -1633,6 +2722,8 @@ bnxt_attach_post(if_ctx_t ctx) ETHER_CRC_LEN; softc->rx_buf_size = min(softc->scctx->isc_max_frame_size, BNXT_PAGE_SIZE); + bnxt_dcb_init(softc); + bnxt_rdma_aux_device_init(softc); failed: return rc; @@ -1646,6 +2737,10 @@ bnxt_detach(if_ctx_t ctx) struct bnxt_vlan_tag *tmp; int i; + bnxt_rdma_aux_device_uninit(softc); + cancel_delayed_work_sync(&softc->fw_reset_task); + cancel_work_sync(&softc->sp_task); + bnxt_dcb_free(softc); SLIST_REMOVE(&pf_list, &softc->list, bnxt_softc_list, next); bnxt_num_pfs--; bnxt_wol_config(ctx); @@ -1655,10 +2750,9 @@ bnxt_detach(if_ctx_t ctx) bnxt_free_ctx_mem(softc); bnxt_clear_ids(softc); iflib_irq_free(ctx, &softc->def_cp_ring.irq); - iflib_config_gtask_deinit(&softc->def_cp_task); /* We need to free() these here... */ for (i = softc->nrxqsets-1; i>=0; i--) { - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) iflib_irq_free(ctx, &softc->nq_rings[i].irq); else iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); @@ -1683,6 +2777,11 @@ bnxt_detach(if_ctx_t ctx) bnxt_free_hwrm_short_cmd_req(softc); BNXT_HWRM_LOCK_DESTROY(softc); + if (!bnxt_num_pfs && bnxt_pf_wq) + destroy_workqueue(bnxt_pf_wq); + + if (softc->pdev) + linux_pci_detach_device(softc->pdev); free(softc->state_bv, M_DEVBUF); pci_disable_busmaster(softc->dev); bnxt_pci_mapping_free(softc); @@ -1759,7 +2858,7 @@ bnxt_hwrm_resource_free(struct bnxt_softc *softc) if (rc) goto fail; - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { rc = bnxt_hwrm_ring_free(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ, &softc->nq_rings[i].ring, @@ -1782,7 +2881,7 @@ static void bnxt_func_reset(struct bnxt_softc *softc) { - if (!BNXT_CHIP_P5(softc)) { + if (!BNXT_CHIP_P5_PLUS(softc)) { bnxt_hwrm_func_reset(softc); return; } @@ -1798,7 +2897,7 @@ bnxt_rss_grp_tbl_init(struct bnxt_softc *softc) int i, j; for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { rgt[i++] = htole16(softc->rx_rings[j].phys_id); rgt[i] = htole16(softc->rx_cp_rings[j].ring.phys_id); } else { @@ -1836,6 +2935,77 @@ static void bnxt_get_port_module_status(struct bnxt_softc *softc) } } +static void bnxt_aux_dev_free(struct bnxt_softc *softc) +{ + kfree(softc->aux_dev); + softc->aux_dev = NULL; +} + +static struct bnxt_aux_dev *bnxt_aux_dev_init(struct bnxt_softc *softc) +{ + struct bnxt_aux_dev *bnxt_adev; + + msleep(1000 * 2); + bnxt_adev = kzalloc(sizeof(*bnxt_adev), GFP_KERNEL); + if (!bnxt_adev) + return ERR_PTR(-ENOMEM); + + return bnxt_adev; +} + +static void bnxt_rdma_aux_device_uninit(struct bnxt_softc *softc) +{ + struct bnxt_aux_dev *bnxt_adev = softc->aux_dev; + + /* Skip if no auxiliary device init was done. */ + if (!(softc->flags & BNXT_FLAG_ROCE_CAP)) + return; + + if (IS_ERR_OR_NULL(bnxt_adev)) + return; + + bnxt_rdma_aux_device_del(softc); + + if (bnxt_adev->id >= 0) + ida_free(&bnxt_aux_dev_ids, bnxt_adev->id); + + bnxt_aux_dev_free(softc); +} + +static void bnxt_rdma_aux_device_init(struct bnxt_softc *softc) +{ + int rc; + + if (!(softc->flags & BNXT_FLAG_ROCE_CAP)) + return; + + softc->aux_dev = bnxt_aux_dev_init(softc); + if (IS_ERR_OR_NULL(softc->aux_dev)) { + device_printf(softc->dev, "Failed to init auxiliary device for ROCE\n"); + goto skip_aux_init; + } + + softc->aux_dev->id = ida_alloc(&bnxt_aux_dev_ids, GFP_KERNEL); + if (softc->aux_dev->id < 0) { + device_printf(softc->dev, "ida alloc failed for ROCE auxiliary device\n"); + bnxt_aux_dev_free(softc); + goto skip_aux_init; + } + + msleep(1000 * 2); + /* If aux bus init fails, continue with netdev init. */ + rc = bnxt_rdma_aux_device_add(softc); + if (rc) { + device_printf(softc->dev, "Failed to add auxiliary device for ROCE\n"); + msleep(1000 * 2); + ida_free(&bnxt_aux_dev_ids, softc->aux_dev->id); + } + device_printf(softc->dev, "%s:%d Added auxiliary device (id %d) for ROCE \n", + __func__, __LINE__, softc->aux_dev->id); +skip_aux_init: + return; +} + /* Device configuration */ static void bnxt_init(if_ctx_t ctx) @@ -1845,7 +3015,7 @@ bnxt_init(if_ctx_t ctx) int i; int rc; - if (!BNXT_CHIP_P5(softc)) { + if (!BNXT_CHIP_P5_PLUS(softc)) { rc = bnxt_hwrm_func_reset(softc); if (rc) return; @@ -1856,8 +3026,7 @@ bnxt_init(if_ctx_t ctx) softc->is_dev_init = true; bnxt_clear_ids(softc); - // TBD -- Check if it is needed for Thor as well - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) goto skip_def_cp_ring; /* Allocate the default completion ring */ softc->def_cp_ring.cons = UINT32_MAX; @@ -1866,6 +3035,8 @@ bnxt_init(if_ctx_t ctx) rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, &softc->def_cp_ring.ring); + bnxt_set_db_mask(softc, &softc->def_cp_ring.ring, + HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL); if (rc) goto fail; skip_def_cp_ring: @@ -1876,15 +3047,18 @@ skip_def_cp_ring: if (rc) goto fail; - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { /* Allocate the NQ */ softc->nq_rings[i].cons = 0; + softc->nq_rings[i].raw_cons = 0; softc->nq_rings[i].v_bit = 1; softc->nq_rings[i].last_idx = UINT32_MAX; bnxt_mark_cpr_invalid(&softc->nq_rings[i]); rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ, &softc->nq_rings[i].ring); + bnxt_set_db_mask(softc, &softc->nq_rings[i].ring, + HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ); if (rc) goto fail; @@ -1892,21 +3066,27 @@ skip_def_cp_ring: } /* Allocate the completion ring */ softc->rx_cp_rings[i].cons = UINT32_MAX; + softc->rx_cp_rings[i].raw_cons = UINT32_MAX; softc->rx_cp_rings[i].v_bit = 1; softc->rx_cp_rings[i].last_idx = UINT32_MAX; + softc->rx_cp_rings[i].toggle = 0; bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, &softc->rx_cp_rings[i].ring); + bnxt_set_db_mask(softc, &softc->rx_cp_rings[i].ring, + HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL); if (rc) goto fail; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_rx_cq(&softc->rx_cp_rings[i], 1); /* Allocate the RX ring */ rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, &softc->rx_rings[i]); + bnxt_set_db_mask(softc, &softc->rx_rings[i], + HWRM_RING_ALLOC_INPUT_RING_TYPE_RX); if (rc) goto fail; softc->db_ops.bnxt_db_rx(&softc->rx_rings[i], 0); @@ -1915,6 +3095,8 @@ skip_def_cp_ring: rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG, &softc->ag_rings[i]); + bnxt_set_db_mask(softc, &softc->ag_rings[i], + HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG); if (rc) goto fail; softc->db_ops.bnxt_db_rx(&softc->ag_rings[i], 0); @@ -1977,21 +3159,27 @@ skip_def_cp_ring: /* Allocate the completion ring */ softc->tx_cp_rings[i].cons = UINT32_MAX; + softc->tx_cp_rings[i].raw_cons = UINT32_MAX; softc->tx_cp_rings[i].v_bit = 1; + softc->tx_cp_rings[i].toggle = 0; bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, &softc->tx_cp_rings[i].ring); + bnxt_set_db_mask(softc, &softc->tx_cp_rings[i].ring, + HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL); if (rc) goto fail; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_tx_cq(&softc->tx_cp_rings[i], 1); /* Allocate the TX ring */ rc = bnxt_hwrm_ring_alloc(softc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, &softc->tx_rings[i]); + bnxt_set_db_mask(softc, &softc->tx_rings[i], + HWRM_RING_ALLOC_INPUT_RING_TYPE_TX); if (rc) goto fail; softc->db_ops.bnxt_db_tx(&softc->tx_rings[i], 0); @@ -2129,17 +3317,15 @@ bnxt_media_change(if_ctx_t ctx) struct ifmedia *ifm = iflib_get_media(ctx); struct ifmediareq ifmr; int rc; + struct bnxt_link_info *link_info = &softc->link_info; if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) return EINVAL; - softc->link_info.req_signal_mode = - HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; - switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_100_T: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB; break; case IFM_1000_KX: @@ -2147,103 +3333,229 @@ bnxt_media_change(if_ctx_t ctx) case IFM_1000_CX: case IFM_1000_SX: case IFM_1000_LX: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB; + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_1GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_1GB; + link_info->force_speed2_nrz = true; + } + break; + case IFM_2500_KX: case IFM_2500_T: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB; break; case IFM_10G_CR1: case IFM_10G_KR: case IFM_10G_LR: case IFM_10G_SR: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB; + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_10GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_10GB; + link_info->force_speed2_nrz = true; + } + break; case IFM_20G_KR2: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB; break; case IFM_25G_CR: case IFM_25G_KR: case IFM_25G_SR: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB; + case IFM_25G_LR: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_25GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_25GB; + link_info->force_speed2_nrz = true; + } + break; + case IFM_40G_CR4: case IFM_40G_KR4: case IFM_40G_LR4: case IFM_40G_SR4: case IFM_40G_XLAUI: case IFM_40G_XLAUI_AC: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB; + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_40GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_40GB; + link_info->force_speed2_nrz = true; + } + break; + case IFM_50G_CR2: case IFM_50G_KR2: + case IFM_50G_KR4: case IFM_50G_SR2: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; + case IFM_50G_LR2: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB; + link_info->force_speed2_nrz = true; + } + break; + case IFM_50G_CP: case IFM_50G_LR: case IFM_50G_SR: case IFM_50G_KR_PAM4: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_50GB; - softc->link_info.req_signal_mode = - HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; - softc->link_info.force_pam4_speed_set_by_user = true; + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_pam4_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_PAM4_SPEEDS_50G) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_50GB; + link_info->force_pam4_speed = true; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB_PAM4_56) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB_PAM4_56; + link_info->force_pam4_56_speed2 = true; + } + break; + case IFM_100G_CR4: case IFM_100G_KR4: case IFM_100G_LR4: case IFM_100G_SR4: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; + case IFM_100G_AUI4: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB; + link_info->force_speed2_nrz = true; + } + break; + case IFM_100G_CP2: case IFM_100G_SR2: - case IFM_100G_KR_PAM4: case IFM_100G_KR2_PAM4: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_100GB; - softc->link_info.req_signal_mode = - HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; - softc->link_info.force_pam4_speed_set_by_user = true; + case IFM_100G_AUI2: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_pam4_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_PAM4_SPEEDS_100G) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_100GB; + link_info->force_pam4_speed = true; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_56) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_56; + link_info->force_pam4_56_speed2 = true; + } + + break; + + case IFM_100G_KR_PAM4: + case IFM_100G_CR_PAM4: + case IFM_100G_DR: + case IFM_100G_AUI2_AC: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_112) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_112; + link_info->force_pam4_112_speed2 = true; + } + break; + case IFM_200G_SR4: case IFM_200G_FR4: case IFM_200G_LR4: case IFM_200G_DR4: case IFM_200G_CR4_PAM4: case IFM_200G_KR4_PAM4: - softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; - softc->link_info.req_link_speed = - HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_200GB; - softc->link_info.force_pam4_speed_set_by_user = true; - softc->link_info.req_signal_mode = - HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_pam4_speeds & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_PAM4_SPEEDS_200G) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_200GB; + link_info->force_pam4_speed = true; + + } else if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_56) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_56; + link_info->force_pam4_56_speed2 = true; + } + + break; + + case IFM_200G_AUI4: + + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_112) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_112; + link_info->force_pam4_112_speed2 = true; + } + break; + + case IFM_400G_FR8: + case IFM_400G_LR8: + case IFM_400G_AUI8: + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_56) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_56; + link_info->force_pam4_56_speed2 = true; + } + + break; + + case IFM_400G_AUI8_AC: + case IFM_400G_DR4: + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + + if (link_info->support_speeds2 & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_112) { + link_info->req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_112; + link_info->force_pam4_112_speed2 = true; + } + + break; + case IFM_1000_T: - softc->link_info.advertising = HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB; - softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; + link_info->advertising = HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB; + link_info->autoneg |= BNXT_AUTONEG_SPEED; break; case IFM_10G_T: - softc->link_info.advertising = HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB; - softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; + link_info->advertising = HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB; + link_info->autoneg |= BNXT_AUTONEG_SPEED; break; default: device_printf(softc->dev, @@ -2251,9 +3563,10 @@ bnxt_media_change(if_ctx_t ctx) /* Fall-through */ case IFM_AUTO: // Auto - softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; + link_info->autoneg |= BNXT_AUTONEG_SPEED; break; } + rc = bnxt_hwrm_set_link_setting(softc, true, true, true); bnxt_media_status(softc->ctx, &ifmr); return rc; @@ -2312,11 +3625,11 @@ bnxt_update_admin_status(if_ctx_t ctx) bnxt_hwrm_port_qstats(softc); - if (BNXT_CHIP_P5(softc) && + if (BNXT_CHIP_P5_PLUS(softc) && (softc->flags & BNXT_FLAG_FW_CAP_EXT_STATS)) bnxt_hwrm_port_qstats_ext(softc); - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { struct ifmediareq ifmr; if (bit_test(softc->state_bv, BNXT_STATE_LINK_CHANGE)) { @@ -2349,10 +3662,11 @@ bnxt_do_enable_intr(struct bnxt_cp_ring *cpr) { struct bnxt_softc *softc = cpr->ring.softc; + if (cpr->ring.phys_id == (uint16_t)HWRM_NA_SIGNATURE) return; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_nq(cpr, 1); else softc->db_ops.bnxt_db_rx_cq(cpr, 1); @@ -2366,7 +3680,7 @@ bnxt_do_disable_intr(struct bnxt_cp_ring *cpr) if (cpr->ring.phys_id == (uint16_t)HWRM_NA_SIGNATURE) return; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_nq(cpr, 0); else softc->db_ops.bnxt_db_rx_cq(cpr, 0); @@ -2381,7 +3695,7 @@ bnxt_intr_enable(if_ctx_t ctx) bnxt_do_enable_intr(&softc->def_cp_ring); for (i = 0; i < softc->nrxqsets; i++) - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_nq(&softc->nq_rings[i], 1); else softc->db_ops.bnxt_db_rx_cq(&softc->rx_cp_rings[i], 1); @@ -2395,7 +3709,7 @@ bnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) { struct bnxt_softc *softc = iflib_get_softc(ctx); - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_nq(&softc->nq_rings[qid], 1); else softc->db_ops.bnxt_db_rx_cq(&softc->tx_cp_rings[qid], 1); @@ -2431,30 +3745,40 @@ bnxt_process_async_msg(struct bnxt_cp_ring *cpr, tx_cmpl_t *cmpl) } } -static void +void process_nq(struct bnxt_softc *softc, uint16_t nqid) { struct bnxt_cp_ring *cpr = &softc->nq_rings[nqid]; nq_cn_t *cmp = (nq_cn_t *) cpr->ring.vaddr; + struct bnxt_cp_ring *tx_cpr = &softc->tx_cp_rings[nqid]; + struct bnxt_cp_ring *rx_cpr = &softc->rx_cp_rings[nqid]; bool v_bit = cpr->v_bit; uint32_t cons = cpr->cons; + uint32_t raw_cons = cpr->raw_cons; uint16_t nq_type, nqe_cnt = 0; while (1) { - if (!NQ_VALID(&cmp[cons], v_bit)) + if (!NQ_VALID(&cmp[cons], v_bit)) { goto done; + } nq_type = NQ_CN_TYPE_MASK & cmp[cons].type; - if (nq_type != NQ_CN_TYPE_CQ_NOTIFICATION) + if (NQE_CN_TYPE(nq_type) != NQ_CN_TYPE_CQ_NOTIFICATION) { bnxt_process_async_msg(cpr, (tx_cmpl_t *)&cmp[cons]); + } else { + tx_cpr->toggle = NQE_CN_TOGGLE(cmp[cons].type); + rx_cpr->toggle = NQE_CN_TOGGLE(cmp[cons].type); + } NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + raw_cons++; nqe_cnt++; } done: if (nqe_cnt) { cpr->cons = cons; + cpr->raw_cons = raw_cons; cpr->v_bit = v_bit; } } @@ -2464,7 +3788,7 @@ bnxt_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) { struct bnxt_softc *softc = iflib_get_softc(ctx); - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { process_nq(softc, qid); softc->db_ops.bnxt_db_nq(&softc->nq_rings[qid], 1); } @@ -2484,7 +3808,7 @@ bnxt_disable_intr(if_ctx_t ctx) * update the index */ for (i = 0; i < softc->nrxqsets; i++) - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_nq(&softc->nq_rings[i], 0); else softc->db_ops.bnxt_db_rx_cq(&softc->rx_cp_rings[i], 0); @@ -2504,7 +3828,7 @@ bnxt_msix_intr_assign(if_ctx_t ctx, int msix) int i; char irq_name[16]; - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) goto skip_default_cp; rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, @@ -2518,7 +3842,7 @@ bnxt_msix_intr_assign(if_ctx_t ctx, int msix) skip_default_cp: for (i=0; i<softc->scctx->isc_nrxqsets; i++) { - if (BNXT_CHIP_P5(softc)) { + if (BNXT_CHIP_P5_PLUS(softc)) { irq = &softc->nq_rings[i].irq; id = softc->nq_rings[i].ring.id; ring = &softc->nq_rings[i]; @@ -2965,7 +4289,7 @@ bnxt_i2c_req(if_ctx_t ctx, struct ifi2creq *i2c) return -EOPNOTSUPP; /* This feature is not supported in older firmware versions */ - if (!BNXT_CHIP_P5(softc) || + if (!BNXT_CHIP_P5_PLUS(softc) || (softc->hwrm_spec_code < 0x10202)) return -EOPNOTSUPP; @@ -2985,6 +4309,7 @@ bnxt_probe_phy(struct bnxt_softc *softc) struct bnxt_link_info *link_info = &softc->link_info; int rc = 0; + softc->phy_flags = 0; rc = bnxt_hwrm_phy_qcaps(softc); if (rc) { device_printf(softc->dev, @@ -3023,57 +4348,161 @@ bnxt_probe_phy(struct bnxt_softc *softc) } static void -add_media(struct bnxt_softc *softc, uint8_t media_type, uint16_t supported, - uint16_t supported_pam4) +add_media(struct bnxt_softc *softc, u8 media_type, u16 supported_NRZ_speeds, + u16 supported_pam4_speeds, u16 supported_speeds2) { + switch (media_type) { case BNXT_MEDIA_CR: - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_CP); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_CP2); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_CR4_PAM4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_CR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_CR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_CR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_CR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_CR1); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_CX); + + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_50G, IFM_50G_CP); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_100G, IFM_100G_CP2); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_200G, IFM_200G_CR4_PAM4); + + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100GB, IFM_100G_CR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_50GB, IFM_50G_CR2); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_CR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_25GB, IFM_25G_CR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_CR1); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_CX); + /* thor2 nrz*/ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB, IFM_100G_CR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB, IFM_50G_CR2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_40GB, IFM_40G_CR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_25GB, IFM_25G_CR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_CR1); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_CX); + /* thor2 PAM56 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB_PAM4_56, IFM_50G_CP); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_56, IFM_100G_CP2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_56, IFM_200G_CR4_PAM4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_56, IFM_400G_AUI8); + /* thor2 PAM112 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_112, IFM_100G_CR_PAM4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_112, IFM_200G_AUI4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_112, IFM_400G_AUI8_AC); + break; case BNXT_MEDIA_LR: - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_LR); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_LR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_LR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_LR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_LR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_LR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_LR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_LX); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_50G, IFM_50G_LR); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_200G, IFM_200G_LR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100GB, IFM_100G_LR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_50GB, IFM_50G_LR2); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_LR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_25GB, IFM_25G_LR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_LR); + /* thor2 nrz*/ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB, IFM_100G_LR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB, IFM_50G_LR2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_40GB, IFM_40G_LR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_25GB, IFM_25G_LR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_LR); + /* thor2 PAM56 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB_PAM4_56, IFM_50G_LR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_56, IFM_100G_AUI2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_56, IFM_200G_LR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_56, IFM_400G_LR8); + /* thor2 PAM112 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_112, IFM_100G_AUI2_AC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_112, IFM_200G_AUI4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_112, IFM_400G_AUI8_AC); + break; case BNXT_MEDIA_SR: - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_SR); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_SR2); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_SR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_SR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_SR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_SR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_SR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_SR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SX); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_50G, IFM_50G_SR); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_100G, IFM_100G_SR2); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_200G, IFM_200G_SR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100GB, IFM_100G_SR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_50GB, IFM_50G_SR2); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_SR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_25GB, IFM_25G_SR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_SR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_SX); + /* thor2 nrz*/ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB, IFM_100G_SR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB, IFM_50G_SR2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_40GB, IFM_40G_SR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_25GB, IFM_25G_SR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_SR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_SX); + /* thor2 PAM56 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB_PAM4_56, IFM_50G_SR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_56, IFM_100G_SR2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_56, IFM_200G_SR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_56, IFM_400G_AUI8); + /* thor2 PAM112 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_112, IFM_100G_AUI2_AC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_112, IFM_200G_AUI4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_112, IFM_400G_DR4); + break; + + case BNXT_MEDIA_ER: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_ER4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100GB, IFM_100G_AUI4); + /* thor2 PAM56 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_50GB_PAM4_56, IFM_50G_LR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_56, IFM_100G_AUI2); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_56, IFM_200G_LR4); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_56, IFM_400G_FR8); + /* thor2 PAM112 */ + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_100GB_PAM4_112, IFM_100G_AUI2_AC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_200GB_PAM4_112, IFM_200G_AUI4_AC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_400GB_PAM4_112, IFM_400G_AUI8_AC); break; case BNXT_MEDIA_KR: - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_KR_PAM4); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_KR2_PAM4); - BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_KR4_PAM4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_KR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_KR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_KR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_20GB, IFM_20G_KR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_50G, IFM_50G_KR_PAM4); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_100G, IFM_100G_KR2_PAM4); + BNXT_IFMEDIA_ADD(supported_pam4_speeds, PAM4_SPEEDS_200G, IFM_200G_KR4_PAM4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100GB, IFM_100G_KR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_50GB, IFM_50G_KR2); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_50GB, IFM_50G_KR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_KR4); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_25GB, IFM_25G_KR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_20GB, IFM_20G_KR2); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_KR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_KX); + break; + + case BNXT_MEDIA_AC: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_25GB, IFM_25G_ACC); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_AOC); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_XLAUI); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_40GB, IFM_40G_XLAUI_AC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_25GB, IFM_25G_ACC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_AOC); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_40GB, IFM_40G_XLAUI); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_40GB, IFM_40G_XLAUI_AC); + break; + + case BNXT_MEDIA_BASECX: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_CX); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_CX); + break; + + case BNXT_MEDIA_BASET: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_T); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_2_5GB, IFM_2500_T); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_T); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_100MB, IFM_100_T); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10MB, IFM_10_T); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_T); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_T); + break; + + case BNXT_MEDIA_BASEKX: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_10GB, IFM_10G_KR); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_2_5GB, IFM_2500_KX); + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_KX); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_10GB, IFM_10G_KR); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_KX); + break; + + case BNXT_MEDIA_BASESGMII: + BNXT_IFMEDIA_ADD(supported_NRZ_speeds, SPEEDS_1GB, IFM_1000_SGMII); + BNXT_IFMEDIA_ADD(supported_speeds2, SPEEDS2_1GB, IFM_1000_SGMII); break; default: @@ -3088,11 +4517,12 @@ static void bnxt_add_media_types(struct bnxt_softc *softc) { struct bnxt_link_info *link_info = &softc->link_info; - uint16_t supported = 0, supported_pam4 = 0; + uint16_t supported_NRZ_speeds = 0, supported_pam4_speeds = 0, supported_speeds2 = 0; uint8_t phy_type = get_phy_type(softc), media_type; - supported = link_info->support_speeds; - supported_pam4 = link_info->support_pam4_speeds; + supported_NRZ_speeds = link_info->support_speeds; + supported_speeds2 = link_info->support_speeds2; + supported_pam4_speeds = link_info->support_pam4_speeds; /* Auto is always supported */ ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); @@ -3101,40 +4531,75 @@ bnxt_add_media_types(struct bnxt_softc *softc) return; switch (phy_type) { - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASECR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR4: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR2: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASECR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASECR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_L: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_S: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_N: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASECR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASECR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASECR8: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASECR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASECR4: + media_type = BNXT_MEDIA_CR; break; - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASELR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR4: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASELR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASELR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASELR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASELR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASELR8: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASELR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASELR4: + media_type = BNXT_MEDIA_LR; break; - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASESR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR10: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR4: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASESR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASESR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4: - case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASEER4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASESR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASESX: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASESR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASESR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASESR8: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASESR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASESR4: + media_type = BNXT_MEDIA_SR; break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASEER: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASEER4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASEER8: + + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASEER2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_400G_BASEER4: + + media_type = BNXT_MEDIA_ER; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: @@ -3142,57 +4607,53 @@ bnxt_add_media_types(struct bnxt_softc *softc) break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_ACTIVE_CABLE: - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_ACC); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_AOC); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_XLAUI); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_XLAUI_AC); - return; + media_type = BNXT_MEDIA_AC; + break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASECX: - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GBHD, IFM_1000_CX); - return; + media_type = BNXT_MEDIA_BASECX; + break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_T); - BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_T); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); - BNXT_IFMEDIA_ADD(supported, SPEEDS_100MB, IFM_100_T); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10MB, IFM_10_T); - return; + media_type = BNXT_MEDIA_BASET; + break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_KX); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); - return; + media_type = BNXT_MEDIA_BASEKX; + break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SGMII); - return; + media_type = BNXT_MEDIA_BASESGMII; + break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: /* Only Autoneg is supported for TYPE_UNKNOWN */ - return; + break; default: /* Only Autoneg is supported for new phy type values */ device_printf(softc->dev, "phy type %d not supported by driver\n", phy_type); - return; + break; } - /* add_media is invoked twice, once with a firmware speed mask of 0 and a valid - * value for both NRZ and PAM4 sig mode. This ensures accurate display of all - * supported medias and currently configured media in the "ifconfig -m" output - */ - - if (link_info->sig_mode == BNXT_SIG_MODE_PAM4) { - add_media(softc, media_type, supported, 0); - add_media(softc, media_type, 0, supported_pam4); - } else { - add_media(softc, media_type, 0, supported_pam4); - add_media(softc, media_type, supported, 0); + switch (link_info->sig_mode) { + case BNXT_SIG_MODE_NRZ: + if (supported_NRZ_speeds != 0) + add_media(softc, media_type, supported_NRZ_speeds, 0, 0); + else + add_media(softc, media_type, 0, 0, supported_speeds2); + break; + case BNXT_SIG_MODE_PAM4: + if (supported_pam4_speeds != 0) + add_media(softc, media_type, 0, supported_pam4_speeds, 0); + else + add_media(softc, media_type, 0, 0, supported_speeds2); + break; + case BNXT_SIG_MODE_PAM4_112: + add_media(softc, media_type, 0, 0, supported_speeds2); + break; } return; @@ -3286,6 +4747,41 @@ exit: return rc; } +#define ETHTOOL_SPEED_1000 1000 +#define ETHTOOL_SPEED_10000 10000 +#define ETHTOOL_SPEED_20000 20000 +#define ETHTOOL_SPEED_25000 25000 +#define ETHTOOL_SPEED_40000 40000 +#define ETHTOOL_SPEED_50000 50000 +#define ETHTOOL_SPEED_100000 100000 +#define ETHTOOL_SPEED_200000 200000 +#define ETHTOOL_SPEED_UNKNOWN -1 + +static u32 +bnxt_fw_to_ethtool_speed(u16 fw_link_speed) +{ + switch (fw_link_speed) { + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: + return ETHTOOL_SPEED_1000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: + return ETHTOOL_SPEED_10000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: + return ETHTOOL_SPEED_20000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: + return ETHTOOL_SPEED_25000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: + return ETHTOOL_SPEED_40000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: + return ETHTOOL_SPEED_50000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: + return ETHTOOL_SPEED_100000; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB: + return ETHTOOL_SPEED_200000; + default: + return ETHTOOL_SPEED_UNKNOWN; + } +} + void bnxt_report_link(struct bnxt_softc *softc) { @@ -3293,6 +4789,10 @@ bnxt_report_link(struct bnxt_softc *softc) const char *duplex = NULL, *flow_ctrl = NULL; const char *signal_mode = ""; + if(softc->edev) + softc->edev->espeed = + bnxt_fw_to_ethtool_speed(link_info->link_speed); + if (link_info->link_up == link_info->last_link_up) { if (!link_info->link_up) return; @@ -3326,7 +4826,10 @@ bnxt_report_link(struct bnxt_softc *softc) signal_mode = "(NRZ) "; break; case BNXT_SIG_MODE_PAM4: - signal_mode = "(PAM4) "; + signal_mode = "(PAM4 56Gbps) "; + break; + case BNXT_SIG_MODE_PAM4_112: + signal_mode = "(PAM4 112Gbps) "; break; default: break; @@ -3364,7 +4867,7 @@ bnxt_handle_isr(void *arg) cpr->int_count++; /* Disable further interrupts for this queue */ - if (!BNXT_CHIP_P5(softc)) + if (!BNXT_CHIP_P5_PLUS(softc)) softc->db_ops.bnxt_db_rx_cq(cpr, 0); return FILTER_SCHEDULE_THREAD; @@ -3376,7 +4879,7 @@ bnxt_handle_def_cp(void *arg) struct bnxt_softc *softc = arg; softc->db_ops.bnxt_db_rx_cq(&softc->def_cp_ring, 0); - GROUPTASK_ENQUEUE(&softc->def_cp_task); + iflib_config_task_enqueue(softc->ctx, &softc->def_cp_task); return FILTER_HANDLED; } @@ -3425,22 +4928,189 @@ bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr) cmp[i].info3_v = !cpr->v_bit; } +static void bnxt_event_error_report(struct bnxt_softc *softc, u32 data1, u32 data2) +{ + u32 err_type = BNXT_EVENT_ERROR_REPORT_TYPE(data1); + + switch (err_type) { + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL: + device_printf(softc->dev, + "1PPS: Received invalid signal on pin%u from the external source. Please fix the signal and reconfigure the pin\n", + BNXT_EVENT_INVALID_SIGNAL_DATA(data2)); + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_PAUSE_STORM: + device_printf(softc->dev, + "Pause Storm detected!\n"); + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD: + device_printf(softc->dev, + "One or more MMIO doorbells dropped by the device! epoch: 0x%x\n", + BNXT_EVENT_DBR_EPOCH(data1)); + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM: { + const char *nvm_err_str; + + if (EVENT_DATA1_NVM_ERR_TYPE_WRITE(data1)) + nvm_err_str = "nvm write error"; + else if (EVENT_DATA1_NVM_ERR_TYPE_ERASE(data1)) + nvm_err_str = "nvm erase error"; + else + nvm_err_str = "unrecognized nvm error"; + + device_printf(softc->dev, + "%s reported at address 0x%x\n", nvm_err_str, + (u32)EVENT_DATA2_NVM_ERR_ADDR(data2)); + break; + } + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD: { + char *threshold_type; + char *dir_str; + + switch (EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1)) { + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN: + threshold_type = "warning"; + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL: + threshold_type = "critical"; + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL: + threshold_type = "fatal"; + break; + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN: + threshold_type = "shutdown"; + break; + default: + device_printf(softc->dev, + "Unknown Thermal threshold type event\n"); + return; + } + if (EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1)) + dir_str = "above"; + else + dir_str = "below"; + device_printf(softc->dev, + "Chip temperature has gone %s the %s thermal threshold!\n", + dir_str, threshold_type); + device_printf(softc->dev, + "Temperature (In Celsius), Current: %u, threshold: %u\n", + BNXT_EVENT_THERMAL_CURRENT_TEMP(data2), + BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2)); + break; + } + case HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DUAL_DATA_RATE_NOT_SUPPORTED: + device_printf(softc->dev, + "Speed change is not supported with dual rate transceivers on this board\n"); + break; + + default: + device_printf(softc->dev, + "FW reported unknown error type: %u, data1: 0x%x data2: 0x%x\n", + err_type, data1, data2); + break; + } +} + static void bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl) { struct hwrm_async_event_cmpl *ae = (void *)cmpl; uint16_t async_id = le16toh(ae->event_id); struct ifmediareq ifmr; + char *type_str; + char *status_desc; + struct bnxt_fw_health *fw_health; + u32 data1 = le32toh(ae->event_data1); + u32 data2 = le32toh(ae->event_data2); switch (async_id) { case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: - if (BNXT_CHIP_P5(softc)) + if (BNXT_CHIP_P5_PLUS(softc)) bit_set(softc->state_bv, BNXT_STATE_LINK_CHANGE); else bnxt_media_status(softc->ctx, &ifmr); break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT: { + bnxt_event_error_report(softc, data1, data2); + goto async_event_process_exit; + } + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_THRESHOLD: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_NQ_UPDATE: + break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY: { + type_str = "Solicited"; + + if (!softc->fw_health) + goto async_event_process_exit; + + softc->fw_reset_timestamp = jiffies; + softc->fw_reset_min_dsecs = ae->timestamp_lo; + if (!softc->fw_reset_min_dsecs) + softc->fw_reset_min_dsecs = BNXT_DFLT_FW_RST_MIN_DSECS; + softc->fw_reset_max_dsecs = le16toh(ae->timestamp_hi); + if (!softc->fw_reset_max_dsecs) + softc->fw_reset_max_dsecs = BNXT_DFLT_FW_RST_MAX_DSECS; + if (EVENT_DATA1_RESET_NOTIFY_FW_ACTIVATION(data1)) { + set_bit(BNXT_STATE_FW_ACTIVATE_RESET, &softc->state); + } else if (EVENT_DATA1_RESET_NOTIFY_FATAL(data1)) { + type_str = "Fatal"; + softc->fw_health->fatalities++; + set_bit(BNXT_STATE_FW_FATAL_COND, &softc->state); + } else if (data2 && BNXT_FW_STATUS_HEALTHY != + EVENT_DATA2_RESET_NOTIFY_FW_STATUS_CODE(data2)) { + type_str = "Non-fatal"; + softc->fw_health->survivals++; + set_bit(BNXT_STATE_FW_NON_FATAL_COND, &softc->state); + } + device_printf(softc->dev, + "%s firmware reset event, data1: 0x%x, data2: 0x%x, min wait %u ms, max wait %u ms\n", + type_str, data1, data2, + softc->fw_reset_min_dsecs * 100, + softc->fw_reset_max_dsecs * 100); + set_bit(BNXT_FW_RESET_NOTIFY_SP_EVENT, &softc->sp_event); + break; + } + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY: { + fw_health = softc->fw_health; + status_desc = "healthy"; + u32 status; + + if (!fw_health) + goto async_event_process_exit; + + if (!EVENT_DATA1_RECOVERY_ENABLED(data1)) { + fw_health->enabled = false; + device_printf(softc->dev, "Driver recovery watchdog is disabled\n"); + break; + } + fw_health->primary = EVENT_DATA1_RECOVERY_MASTER_FUNC(data1); + fw_health->tmr_multiplier = + DIV_ROUND_UP(fw_health->polling_dsecs * HZ, + HZ * 10); + fw_health->tmr_counter = fw_health->tmr_multiplier; + if (!fw_health->enabled) + fw_health->last_fw_heartbeat = + bnxt_fw_health_readl(softc, BNXT_FW_HEARTBEAT_REG); + fw_health->last_fw_reset_cnt = + bnxt_fw_health_readl(softc, BNXT_FW_RESET_CNT_REG); + status = bnxt_fw_health_readl(softc, BNXT_FW_HEALTH_REG); + if (status != BNXT_FW_STATUS_HEALTHY) + status_desc = "unhealthy"; + device_printf(softc->dev, + "Driver recovery watchdog, role: %s, firmware status: 0x%x (%s), resets: %u\n", + fw_health->primary ? "primary" : "backup", status, + status_desc, fw_health->last_fw_reset_cnt); + if (!fw_health->enabled) { + /* Make sure tmr_counter is set and seen by + * bnxt_health_check() before setting enabled + */ + smp_mb(); + fw_health->enabled = true; + } + goto async_event_process_exit; + } + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE: case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE: case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: @@ -3458,14 +5128,18 @@ bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl) "Unhandled async completion type %u\n", async_id); break; default: - device_printf(softc->dev, - "Unknown async completion type %u\n", async_id); + dev_dbg(softc->dev, "Unknown Async event completion type %u\n", + async_id); break; } + bnxt_queue_sp_work(softc); + +async_event_process_exit: + bnxt_ulp_async_events(softc, ae); } static void -bnxt_def_cp_task(void *context) +bnxt_def_cp_task(void *context, int pending) { if_ctx_t ctx = context; struct bnxt_softc *softc = iflib_get_softc(ctx); @@ -3495,8 +5169,10 @@ bnxt_def_cp_task(void *context) break; case CMPL_BASE_TYPE_TX_L2: case CMPL_BASE_TYPE_RX_L2: + case CMPL_BASE_TYPE_RX_L2_V3: case CMPL_BASE_TYPE_RX_AGG: case CMPL_BASE_TYPE_RX_TPA_START: + case CMPL_BASE_TYPE_RX_TPA_START_V3: case CMPL_BASE_TYPE_RX_TPA_END: case CMPL_BASE_TYPE_STAT_EJECT: case CMPL_BASE_TYPE_HWRM_DONE: @@ -3507,12 +5183,12 @@ bnxt_def_cp_task(void *context) case CMPL_BASE_TYPE_DBQ_EVENT: case CMPL_BASE_TYPE_QP_EVENT: case CMPL_BASE_TYPE_FUNC_EVENT: - device_printf(softc->dev, - "Unhandled completion type %u\n", type); + dev_dbg(softc->dev, "Unhandled Async event completion type %u\n", + type); break; default: - device_printf(softc->dev, - "Unknown completion type %u\n", type); + dev_dbg(softc->dev, "Unknown Async event completion type %u\n", + type); break; } } @@ -3617,6 +5293,8 @@ bnxt_get_baudrate(struct bnxt_link_info *link) return IF_Mbps(10); case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB: return IF_Gbps(200); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_400GB: + return IF_Gbps(400); } return IF_Gbps(100); } diff --git a/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h b/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h new file mode 100644 index 000000000000..8f48609e7f6f --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Uverbs ABI header file + */ + +#ifndef __BNXT_RE_UVERBS_ABI_H__ +#define __BNXT_RE_UVERBS_ABI_H__ + +#include <asm/types.h> +#include <linux/types.h> + +#define BNXT_RE_ABI_VERSION 6 + +enum { + BNXT_RE_COMP_MASK_UCNTX_WC_DPI_ENABLED = 0x01, + BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED = 0x02, + BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED = 0x04, + BNXT_RE_COMP_MASK_UCNTX_MQP_EX_SUPPORTED = 0x08, + BNXT_RE_COMP_MASK_UCNTX_DBR_PACING_ENABLED = 0x10, + BNXT_RE_COMP_MASK_UCNTX_DBR_RECOVERY_ENABLED = 0x20, + BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED = 0x40 +}; + +enum { + BNXT_RE_COMP_MASK_REQ_UCNTX_POW2_SUPPORT = 0x01, + BNXT_RE_COMP_MASK_REQ_UCNTX_RSVD_WQE = 0x02 +}; + +struct bnxt_re_uctx_req { + __aligned_u64 comp_mask; +}; + +#define BNXT_RE_CHIP_ID0_CHIP_NUM_SFT 0x00 +#define BNXT_RE_CHIP_ID0_CHIP_REV_SFT 0x10 +#define BNXT_RE_CHIP_ID0_CHIP_MET_SFT 0x18 +struct bnxt_re_uctx_resp { + __u32 dev_id; + __u32 max_qp; + __u32 pg_size; + __u32 cqe_sz; + __u32 max_cqd; + __u32 chip_id0; + __u32 chip_id1; + __u32 modes; + __aligned_u64 comp_mask; +} __attribute__((packed)); + +enum { + BNXT_RE_COMP_MASK_PD_HAS_WC_DPI = 0x01, + BNXT_RE_COMP_MASK_PD_HAS_DBR_BAR_ADDR = 0x02, +}; + +struct bnxt_re_pd_resp { + __u32 pdid; + __u32 dpi; + __u64 dbr; + __u64 comp_mask; + __u32 wcdpi; + __u64 dbr_bar_addr; +} __attribute__((packed)); + +enum { + BNXT_RE_COMP_MASK_CQ_HAS_DB_INFO = 0x01, + BNXT_RE_COMP_MASK_CQ_HAS_WC_DPI = 0x02, + BNXT_RE_COMP_MASK_CQ_HAS_CQ_PAGE = 0x04, +}; + +enum { + BNXT_RE_COMP_MASK_CQ_REQ_HAS_CAP_MASK = 0x1 +}; + +enum { + BNXT_RE_COMP_MASK_CQ_REQ_CAP_DBR_RECOVERY = 0x1, + BNXT_RE_COMP_MASK_CQ_REQ_CAP_DBR_PACING_NOTIFY = 0x2 +}; + +#define BNXT_RE_IS_DBR_PACING_NOTIFY_CQ(_req) \ + (_req.comp_mask & BNXT_RE_COMP_MASK_CQ_REQ_HAS_CAP_MASK && \ + _req.cq_capability & BNXT_RE_COMP_MASK_CQ_REQ_CAP_DBR_PACING_NOTIFY) + +#define BNXT_RE_IS_DBR_RECOV_CQ(_req) \ + (_req.comp_mask & BNXT_RE_COMP_MASK_CQ_REQ_HAS_CAP_MASK && \ + _req.cq_capability & BNXT_RE_COMP_MASK_CQ_REQ_CAP_DBR_RECOVERY) + +struct bnxt_re_cq_req { + __u64 cq_va; + __u64 cq_handle; + __aligned_u64 comp_mask; + __u16 cq_capability; +} __attribute__((packed)); + +struct bnxt_re_cq_resp { + __u32 cqid; + __u32 tail; + __u32 phase; + __u32 rsvd; + __aligned_u64 comp_mask; + __u32 dpi; + __u64 dbr; + __u32 wcdpi; + __u64 uctx_cq_page; +} __attribute__((packed)); + +struct bnxt_re_resize_cq_req { + __u64 cq_va; +} __attribute__((packed)); + +struct bnxt_re_qp_req { + __u64 qpsva; + __u64 qprva; + __u64 qp_handle; +} __attribute__((packed)); + +struct bnxt_re_qp_resp { + __u32 qpid; +} __attribute__((packed)); + +struct bnxt_re_srq_req { + __u64 srqva; + __u64 srq_handle; +} __attribute__((packed)); + +struct bnxt_re_srq_resp { + __u32 srqid; +} __attribute__((packed)); + +/* Modify QP */ +enum { + BNXT_RE_COMP_MASK_MQP_EX_PPP_REQ_EN_MASK = 0x1, + BNXT_RE_COMP_MASK_MQP_EX_PPP_REQ_EN = 0x1, + BNXT_RE_COMP_MASK_MQP_EX_PATH_MTU_MASK = 0x2 +}; + +struct bnxt_re_modify_qp_ex_req { + __aligned_u64 comp_mask; + __u32 dpi; + __u32 rsvd; +} __packed; + +struct bnxt_re_modify_qp_ex_resp { + __aligned_u64 comp_mask; + __u32 ppp_st_idx; + __u32 path_mtu; +} __packed; + +enum bnxt_re_shpg_offt { + BNXT_RE_BEG_RESV_OFFT = 0x00, + BNXT_RE_AVID_OFFT = 0x10, + BNXT_RE_AVID_SIZE = 0x04, + BNXT_RE_END_RESV_OFFT = 0xFF0 +}; +#endif diff --git a/sys/dev/bnxt/bnxt_re/bnxt_re.h b/sys/dev/bnxt/bnxt_re/bnxt_re.h new file mode 100644 index 000000000000..fe7a27f4e216 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/bnxt_re.h @@ -0,0 +1,1077 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: main (header) + */ + +#ifndef __BNXT_RE_H__ +#define __BNXT_RE_H__ + +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/mutex.h> +#include <linux/list.h> +#include <linux/rculist.h> +#include <linux/spinlock.h> +#include <net/ipv6.h> +#include <linux/if_ether.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/interrupt.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <rdma/ib_verbs.h> +#include <rdma/ib_user_verbs.h> +#include <rdma/ib_umem.h> +#include <rdma/ib_addr.h> +#include <rdma/ib_mad.h> +#include <rdma/ib_cache.h> +#include <linux/pci.h> + +#include "bnxt.h" +#include "bnxt_ulp.h" +#include "hsi_struct_def.h" +#include "qplib_res.h" +#include "qplib_sp.h" +#include "qplib_fp.h" +#include "qplib_rcfw.h" +#include "ib_verbs.h" +#include "stats.h" + +#define ROCE_DRV_MODULE_NAME "bnxt_re" +#define ROCE_DRV_MODULE_VERSION "230.0.133.0" +#define ROCE_DRV_MODULE_RELDATE "April 22, 2024" + +#define BNXT_RE_REF_WAIT_COUNT 20 +#define BNXT_RE_ROCE_V1_ETH_TYPE 0x8915 +#define BNXT_RE_ROCE_V2_PORT_NO 4791 +#define BNXT_RE_RES_FREE_WAIT_COUNT 1000 + +#define BNXT_RE_PAGE_SHIFT_4K (12) +#define BNXT_RE_PAGE_SHIFT_8K (13) +#define BNXT_RE_PAGE_SHIFT_64K (16) +#define BNXT_RE_PAGE_SHIFT_2M (21) +#define BNXT_RE_PAGE_SHIFT_8M (23) +#define BNXT_RE_PAGE_SHIFT_1G (30) + +#define BNXT_RE_PAGE_SIZE_4K BIT(BNXT_RE_PAGE_SHIFT_4K) +#define BNXT_RE_PAGE_SIZE_8K BIT(BNXT_RE_PAGE_SHIFT_8K) +#define BNXT_RE_PAGE_SIZE_64K BIT(BNXT_RE_PAGE_SHIFT_64K) +#define BNXT_RE_PAGE_SIZE_2M BIT(BNXT_RE_PAGE_SHIFT_2M) +#define BNXT_RE_PAGE_SIZE_8M BIT(BNXT_RE_PAGE_SHIFT_8M) +#define BNXT_RE_PAGE_SIZE_1G BIT(BNXT_RE_PAGE_SHIFT_1G) + +#define BNXT_RE_MAX_MR_SIZE_LOW BIT(BNXT_RE_PAGE_SHIFT_1G) +#define BNXT_RE_MAX_MR_SIZE_HIGH BIT(39) +#define BNXT_RE_MAX_MR_SIZE BNXT_RE_MAX_MR_SIZE_HIGH + +/* Number of MRs to reserve for PF, leaving remainder for VFs */ +#define BNXT_RE_RESVD_MR_FOR_PF (32 * 1024) +#define BNXT_RE_MAX_GID_PER_VF 128 + +#define BNXT_RE_MAX_VF_QPS_PER_PF (6 * 1024) + +/** + * min_not_zero - return the minimum that is _not_ zero, unless both are zero + * @x: value1 + * @y: value2 + */ +#ifndef min_not_zero +#define min_not_zero(x, y) ({ \ + typeof(x) __x = (x); \ + typeof(y) __y = (y); \ + __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) +#endif + +struct ib_mr_init_attr { + int max_reg_descriptors; + u32 flags; +}; + +struct bnxt_re_dev; + +int bnxt_re_register_netdevice_notifier(struct notifier_block *nb); +int bnxt_re_unregister_netdevice_notifier(struct notifier_block *nb); +int ib_register_device_compat(struct bnxt_re_dev *rdev); + +#ifndef __struct_group +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } +#endif /* __struct_group */ +#ifndef struct_group_attr +#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ + __struct_group(/* no tag */, NAME, ATTRS, MEMBERS) +#endif /* struct_group_attr */ +/* + * Percentage of resources of each type reserved for PF. + * Remaining resources are divided equally among VFs. + * [0, 100] + */ + +#define BNXT_RE_RQ_WQE_THRESHOLD 32 +#define BNXT_RE_UD_QP_HW_STALL 0x400000 + +/* + * Setting the default ack delay value to 16, which means + * the default timeout is approx. 260ms(4 usec * 2 ^(timeout)) + */ + +#define BNXT_RE_DEFAULT_ACK_DELAY 16 +#define BNXT_RE_BOND_PF_MAX 2 + +#define BNXT_RE_STATS_CTX_UPDATE_TIMER 250 +#define BNXT_RE_30SEC_MSEC (30 * 1000) + +#define BNXT_RE_BOND_RESCHED_CNT 10 + +#define BNXT_RE_CHIP_NUM_57454 0xC454 +#define BNXT_RE_CHIP_NUM_57452 0xC452 + +#define BNXT_RE_CHIP_NUM_5745X(chip_num) \ + ((chip_num) == BNXT_RE_CHIP_NUM_57454 || \ + (chip_num) == BNXT_RE_CHIP_NUM_57452) + +#define BNXT_RE_MIN_KERNEL_QP_TX_DEPTH 4096 +#define BNXT_RE_STOP_QPS_BUDGET 200 + +#define BNXT_RE_HWRM_CMD_TIMEOUT(rdev) \ + ((rdev)->chip_ctx->hwrm_cmd_max_timeout * 1000) + +extern unsigned int min_tx_depth; +extern struct mutex bnxt_re_dev_lock; +extern struct mutex bnxt_re_mutex; +extern struct list_head bnxt_re_dev_list; + +struct bnxt_re_ring_attr { + dma_addr_t *dma_arr; + int pages; + int type; + u32 depth; + u32 lrid; /* Logical ring id */ + u16 flags; + u8 mode; + u8 rsvd; +}; + +#define BNXT_RE_MAX_DEVICES 256 +#define BNXT_RE_MSIX_FROM_MOD_PARAM -1 +#define BNXT_RE_MIN_MSIX 2 +#define BNXT_RE_MAX_MSIX_VF 2 +#define BNXT_RE_MAX_MSIX_PF 9 +#define BNXT_RE_MAX_MSIX_NPAR_PF 5 +#define BNXT_RE_MAX_MSIX 64 +#define BNXT_RE_MAX_MSIX_GEN_P5_PF BNXT_RE_MAX_MSIX +#define BNXT_RE_GEN_P5_MAX_VF 64 + +struct bnxt_re_nq_record { + struct bnxt_msix_entry msix_entries[BNXT_RE_MAX_MSIX]; + /* FP Notification Queue (CQ & SRQ) */ + struct bnxt_qplib_nq nq[BNXT_RE_MAX_MSIX]; + int num_msix; + int max_init; + struct mutex load_lock; +}; + +struct bnxt_re_work { + struct work_struct work; + unsigned long event; + struct bnxt_re_dev *rdev; + struct ifnet *vlan_dev; + bool do_lag; + + /* netdev where we received the event */ + struct ifnet *netdev; + struct auxiliary_device *adev; +}; + +/* + * Data structure and defines to handle + * recovery + */ +#define BNXT_RE_RECOVERY_IB_UNINIT_WAIT_RETRY 20 +#define BNXT_RE_RECOVERY_IB_UNINIT_WAIT_TIME_MS 30000 /* 30sec timeout */ +#define BNXT_RE_PRE_RECOVERY_REMOVE 0x1 +#define BNXT_RE_COMPLETE_REMOVE 0x2 +#define BNXT_RE_POST_RECOVERY_INIT 0x4 +#define BNXT_RE_COMPLETE_INIT 0x8 +#define BNXT_RE_COMPLETE_SHUTDOWN 0x10 + +/* QP1 SQ entry data strucutre */ +struct bnxt_re_sqp_entries { + u64 wrid; + struct bnxt_qplib_sge sge; + /* For storing the actual qp1 cqe */ + struct bnxt_qplib_cqe cqe; + struct bnxt_re_qp *qp1_qp; +}; + +/* GSI QP mode enum */ +enum bnxt_re_gsi_mode { + BNXT_RE_GSI_MODE_INVALID = 0, + BNXT_RE_GSI_MODE_ALL = 1, + BNXT_RE_GSI_MODE_ROCE_V1, + BNXT_RE_GSI_MODE_ROCE_V2_IPV4, + BNXT_RE_GSI_MODE_ROCE_V2_IPV6, + BNXT_RE_GSI_MODE_UD +}; + +enum bnxt_re_roce_cap { + BNXT_RE_FLAG_ROCEV1_CAP = 1, + BNXT_RE_FLAG_ROCEV2_CAP, + BNXT_RE_FLAG_ROCEV1_V2_CAP, +}; + +#define BNXT_RE_MAX_GSI_SQP_ENTRIES 1024 +struct bnxt_re_gsi_context { + u8 gsi_qp_mode; + bool first_cq_created; + /* Start: used only in gsi_mode_all */ + struct bnxt_re_qp *gsi_qp; + struct bnxt_re_qp *gsi_sqp; + struct bnxt_re_ah *gsi_sah; + struct bnxt_re_sqp_entries *sqp_tbl; + /* End: used only in gsi_mode_all */ +}; + +struct bnxt_re_tc_rec { + u8 cos_id_roce; + u8 tc_roce; + u8 cos_id_cnp; + u8 tc_cnp; + u8 tc_def; + u8 cos_id_def; + u8 max_tc; + u8 roce_prio; + u8 cnp_prio; + u8 roce_dscp; + u8 cnp_dscp; + u8 prio_valid; + u8 dscp_valid; + bool ecn_enabled; + bool serv_type_enabled; + u64 cnp_dscp_bv; + u64 roce_dscp_bv; +}; + +struct bnxt_re_dscp2pri { + u8 dscp; + u8 mask; + u8 pri; +}; + +struct bnxt_re_cos2bw_cfg { + u8 pad[3]; + struct_group_attr(cfg, __packed, + u8 queue_id; + __le32 min_bw; + __le32 max_bw; + u8 tsa; + u8 pri_lvl; + u8 bw_weight; + ); + u8 unused; +}; + +#define BNXT_RE_AEQ_IDX 0 +#define BNXT_RE_MAX_SGID_ENTRIES 256 + +#define BNXT_RE_DBGFS_FILE_MEM 65536 +enum { + BNXT_RE_STATS_QUERY = 1, + BNXT_RE_QP_QUERY = 2, + BNXT_RE_SERVICE_FN_QUERY = 3, +}; + +struct bnxt_re_dbg_file { + struct bnxt_re_dev *rdev; + u32 type; + union { + struct bnxt_qplib_query_stats_info sinfo; + struct bnxt_qplib_query_fn_info fninfo; + }params; + char dbg_buf[BNXT_RE_DBGFS_FILE_MEM]; +}; + +struct bnxt_re_debug_entries { + /* Dir entries */ + struct dentry *qpinfo_dir; + struct dentry *service_fn_dir; + /* file entries */ + struct dentry *stat_query; + struct bnxt_re_dbg_file stat_file; + struct dentry *qplist_query; + struct bnxt_re_dbg_file qp_file; + struct dentry *service_fn_query; + struct bnxt_re_dbg_file service_fn_file; +}; + +struct bnxt_re_en_dev_info { + struct list_head en_list; + struct bnxt_en_dev *en_dev; + struct bnxt_re_dev *rdev; + unsigned long flags; +#define BNXT_RE_FLAG_EN_DEV_NETDEV_REG 0 +#define BNXT_RE_FLAG_EN_DEV_PRIMARY_DEV 1 +#define BNXT_RE_FLAG_EN_DEV_SECONDARY_DEV 2 + u8 wqe_mode; + u8 gsi_mode; + bool te_bypass; + bool ib_uninit_done; + u32 num_msix_requested; + wait_queue_head_t waitq; +}; + +#define BNXT_RE_DB_FIFO_ROOM_MASK_P5 0x1FFF8000 +#define BNXT_RE_MAX_FIFO_DEPTH_P5 0x2c00 +#define BNXT_RE_DB_FIFO_ROOM_SHIFT 15 + +#define BNXT_RE_DB_FIFO_ROOM_MASK_P7 0x3FFF8000 +#define BNXT_RE_MAX_FIFO_DEPTH_P7 0x8000 + +#define BNXT_RE_DB_FIFO_ROOM_MASK(ctx) \ + (_is_chip_p7((ctx)) ? \ + BNXT_RE_DB_FIFO_ROOM_MASK_P7 :\ + BNXT_RE_DB_FIFO_ROOM_MASK_P5) +#define BNXT_RE_MAX_FIFO_DEPTH(ctx) \ + (_is_chip_p7((ctx)) ? \ + BNXT_RE_MAX_FIFO_DEPTH_P7 :\ + BNXT_RE_MAX_FIFO_DEPTH_P5) + +struct bnxt_dbq_nq_list { + int num_nql_entries; + u16 nq_id[16]; +}; + +#define BNXT_RE_ASYNC_ERR_REP_BASE(_type) \ + (ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_##_type) + +#define BNXT_RE_ASYNC_ERR_DBR_TRESH(_type) \ + (ASYNC_EVENT_CMPL_ERROR_REPORT_DOORBELL_DROP_THRESHOLD_##_type) + +#define BNXT_RE_EVENT_DBR_EPOCH(data) \ + (((data) & \ + BNXT_RE_ASYNC_ERR_DBR_TRESH(EVENT_DATA1_EPOCH_MASK)) >> \ + BNXT_RE_ASYNC_ERR_DBR_TRESH(EVENT_DATA1_EPOCH_SFT)) + +#define BNXT_RE_EVENT_ERROR_REPORT_TYPE(data1) \ + (((data1) & \ + BNXT_RE_ASYNC_ERR_REP_BASE(TYPE_MASK)) >> \ + BNXT_RE_ASYNC_ERR_REP_BASE(TYPE_SFT)) + +#define BNXT_RE_DBR_LIST_ADD(_rdev, _res, _type) \ +{ \ + spin_lock(&(_rdev)->res_list[_type].lock); \ + list_add_tail(&(_res)->dbr_list, \ + &(_rdev)->res_list[_type].head); \ + spin_unlock(&(_rdev)->res_list[_type].lock); \ +} + +#define BNXT_RE_DBR_LIST_DEL(_rdev, _res, _type) \ +{ \ + spin_lock(&(_rdev)->res_list[_type].lock); \ + list_del(&(_res)->dbr_list); \ + spin_unlock(&(_rdev)->res_list[_type].lock); \ +} + +#define BNXT_RE_CQ_PAGE_LIST_ADD(_uctx, _cq) \ +{ \ + mutex_lock(&(_uctx)->cq_lock); \ + list_add_tail(&(_cq)->cq_list, &(_uctx)->cq_list); \ + mutex_unlock(&(_uctx)->cq_lock); \ +} + +#define BNXT_RE_CQ_PAGE_LIST_DEL(_uctx, _cq) \ +{ \ + mutex_lock(&(_uctx)->cq_lock); \ + list_del(&(_cq)->cq_list); \ + mutex_unlock(&(_uctx)->cq_lock); \ +} + +#define BNXT_RE_NETDEV_EVENT(event, x) \ + do { \ + if ((event) == (x)) \ + return #x; \ + } while (0) + +/* Do not change the seq of this enum which is followed by dbr recov */ +enum { + BNXT_RE_RES_TYPE_CQ = 0, + BNXT_RE_RES_TYPE_UCTX, + BNXT_RE_RES_TYPE_QP, + BNXT_RE_RES_TYPE_SRQ, + BNXT_RE_RES_TYPE_MAX +}; + +struct bnxt_re_dbr_res_list { + struct list_head head; + spinlock_t lock; +}; + +struct bnxt_re_dbr_drop_recov_work { + struct work_struct work; + struct bnxt_re_dev *rdev; + u32 curr_epoch; +}; + +struct bnxt_re_aer_work { + struct work_struct work; + struct bnxt_re_dev *rdev; +}; + +struct bnxt_re_dbq_stats { + u64 fifo_occup_slab_1; + u64 fifo_occup_slab_2; + u64 fifo_occup_slab_3; + u64 fifo_occup_slab_4; + u64 fifo_occup_water_mark; + u64 do_pacing_slab_1; + u64 do_pacing_slab_2; + u64 do_pacing_slab_3; + u64 do_pacing_slab_4; + u64 do_pacing_slab_5; + u64 do_pacing_water_mark; +}; + +/* Device debug statistics */ +struct bnxt_re_drv_dbg_stats { + struct bnxt_re_dbq_stats dbq; +}; + +/* DB pacing counters */ +struct bnxt_re_dbr_sw_stats { + u64 dbq_int_recv; + u64 dbq_int_en; + u64 dbq_pacing_resched; + u64 dbq_pacing_complete; + u64 dbq_pacing_alerts; + u64 dbr_drop_recov_events; + u64 dbr_drop_recov_timeouts; + u64 dbr_drop_recov_timeout_users; + u64 dbr_drop_recov_event_skips; +}; + +struct bnxt_re_dev { + struct ib_device ibdev; + struct list_head list; + atomic_t ref_count; + atomic_t sched_count; + unsigned long flags; +#define BNXT_RE_FLAG_NETDEV_REGISTERED 0 +#define BNXT_RE_FLAG_IBDEV_REGISTERED 1 +#define BNXT_RE_FLAG_GOT_MSIX 2 +#define BNXT_RE_FLAG_HAVE_L2_REF 3 +#define BNXT_RE_FLAG_ALLOC_RCFW 4 +#define BNXT_RE_FLAG_NET_RING_ALLOC 5 +#define BNXT_RE_FLAG_RCFW_CHANNEL_EN 6 +#define BNXT_RE_FLAG_ALLOC_CTX 7 +#define BNXT_RE_FLAG_STATS_CTX_ALLOC 8 +#define BNXT_RE_FLAG_STATS_CTX2_ALLOC 9 +#define BNXT_RE_FLAG_RCFW_CHANNEL_INIT 10 +#define BNXT_RE_FLAG_WORKER_REG 11 +#define BNXT_RE_FLAG_TBLS_ALLOCINIT 12 +#define BNXT_RE_FLAG_SETUP_NQ 13 +#define BNXT_RE_FLAG_BOND_DEV_REGISTERED 14 +#define BNXT_RE_FLAG_PER_PORT_DEBUG_INFO 15 +#define BNXT_RE_FLAG_DEV_LIST_INITIALIZED 16 +#define BNXT_RE_FLAG_ERR_DEVICE_DETACHED 17 +#define BNXT_RE_FLAG_INIT_DCBX_CC_PARAM 18 +#define BNXT_RE_FLAG_STOP_IN_PROGRESS 20 +#define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29 +#define BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS 30 + struct ifnet *netdev; + struct auxiliary_device *adev; + struct bnxt_qplib_chip_ctx *chip_ctx; + struct bnxt_en_dev *en_dev; + struct bnxt_re_nq_record nqr; + int id; + struct delayed_work worker; + u16 worker_30s; + struct bnxt_re_tc_rec tc_rec[2]; + u8 cur_prio_map; + /* RCFW Channel */ + struct bnxt_qplib_rcfw rcfw; + /* Device Resources */ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_res qplib_res; + struct bnxt_qplib_dpi dpi_privileged; + struct bnxt_qplib_cc_param cc_param; + struct mutex cc_lock; + struct mutex qp_lock; + struct list_head qp_list; + u8 roce_mode; + + /* Max of 2 lossless traffic class supported per port */ + u16 cosq[2]; + /* Start: QP for handling QP1 packets */ + struct bnxt_re_gsi_context gsi_ctx; + /* End: QP for handling QP1 packets */ + bool is_virtfn; + u32 num_vfs; + u32 espeed; + /* + * For storing the speed of slave interfaces. + * Same as espeed when bond is not configured + */ + u32 sl_espeed; + /* To be used for a workaround for ISER stack */ + u32 min_tx_depth; + /* To enable qp debug info. Disabled during driver load */ + u32 en_qp_dbg; + /* Array to handle gid mapping */ + char *gid_map; + + struct bnxt_re_device_stats stats; + struct bnxt_re_drv_dbg_stats *dbg_stats; + /* debugfs to expose per port information*/ + struct dentry *port_debug_dir; + struct dentry *info; + struct dentry *drv_dbg_stats; + struct dentry *sp_perf_stats; + struct dentry *pdev_debug_dir; + struct dentry *pdev_qpinfo_dir; + struct bnxt_re_debug_entries *dbg_ent; + struct workqueue_struct *resolve_wq; + struct list_head mac_wq_list; + struct workqueue_struct *dcb_wq; + struct workqueue_struct *aer_wq; + u32 event_bitmap[3]; + bool unreg_sched; + u64 dbr_throttling_reg_off; + u64 dbr_aeq_arm_reg_off; + u64 dbr_db_fifo_reg_off; + void *dbr_page; + u64 dbr_bar_addr; + u32 pacing_algo_th; + u32 pacing_en_int_th; + u32 do_pacing_save; + struct workqueue_struct *dbq_wq; + struct workqueue_struct *dbr_drop_recov_wq; + struct work_struct dbq_fifo_check_work; + struct delayed_work dbq_pacing_work; + /* protect DB pacing */ + struct mutex dbq_lock; + /* Control DBR pacing feature. Set if enabled */ + bool dbr_pacing; + /* Control DBR recovery feature. Set if enabled */ + bool dbr_drop_recov; + bool user_dbr_drop_recov; + /* DBR recovery feature. Set if running */ + bool dbr_recovery_on; + u32 user_dbr_drop_recov_timeout; + /* + * Value used for pacing algo when pacing is active + */ +#define BNXT_RE_MAX_DBR_DO_PACING 0xFFFF + u32 dbr_do_pacing; + u32 dbq_watermark; /* Current watermark set in HW registers */ + u32 dbq_nq_id; /* Current NQ ID for DBQ events */ + u32 dbq_pacing_time; /* ms */ + u32 dbr_def_do_pacing; /* do_pacing when no congestion */ + u32 dbr_evt_curr_epoch; + bool dbq_int_disable; + + bool mod_exit; + struct bnxt_re_dbr_sw_stats *dbr_sw_stats; + struct bnxt_re_dbr_res_list res_list[BNXT_RE_RES_TYPE_MAX]; + struct bnxt_dbq_nq_list nq_list; + char dev_name[IB_DEVICE_NAME_MAX]; + atomic_t dbq_intr_running; + u32 num_msix_requested; + unsigned char *dev_addr; /* For netdev->dev_addr */ +}; + +#define BNXT_RE_RESOLVE_RETRY_COUNT_US 5000000 /* 5 sec */ +struct bnxt_re_resolve_dmac_work{ + struct work_struct work; + struct list_head list; + struct bnxt_re_dev *rdev; + struct ib_ah_attr *ah_attr; + struct bnxt_re_ah_info *ah_info; + atomic_t status_wait; +}; + +static inline u8 bnxt_re_get_prio(u8 prio_map) +{ + u8 prio = 0xFF; + + for (prio = 0; prio < 8; prio++) + if (prio_map & (1UL << prio)) + break; + return prio; +} + +/* This should be called with bnxt_re_dev_lock mutex held */ +static inline bool __bnxt_re_is_rdev_valid(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_dev *tmp_rdev; + + list_for_each_entry(tmp_rdev, &bnxt_re_dev_list, list) { + if (rdev == tmp_rdev) + return true; + } + return false; +} + +static inline bool bnxt_re_is_rdev_valid(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_dev *tmp_rdev; + + mutex_lock(&bnxt_re_dev_lock); + list_for_each_entry(tmp_rdev, &bnxt_re_dev_list, list) { + if (rdev == tmp_rdev) { + mutex_unlock(&bnxt_re_dev_lock); + return true; + } + } + mutex_unlock(&bnxt_re_dev_lock); + + pr_debug("bnxt_re: %s : Invalid rdev received rdev = %p\n", + __func__, rdev); + return false; +} + +int bnxt_re_send_hwrm_cmd(struct bnxt_re_dev *rdev, void *cmd, + int cmdlen); +void bnxt_re_stopqps_and_ib_uninit(struct bnxt_re_dev *rdev); +int bnxt_re_set_hwrm_dscp2pri(struct bnxt_re_dev *rdev, + struct bnxt_re_dscp2pri *d2p, u16 count, + u16 target_id); +int bnxt_re_query_hwrm_dscp2pri(struct bnxt_re_dev *rdev, + struct bnxt_re_dscp2pri *d2p, u16 *count, + u16 target_id); +int bnxt_re_query_hwrm_qportcfg(struct bnxt_re_dev *rdev, + struct bnxt_re_tc_rec *cnprec, u16 tid); +int bnxt_re_hwrm_cos2bw_qcfg(struct bnxt_re_dev *rdev, u16 target_id, + struct bnxt_re_cos2bw_cfg *cfg); +int bnxt_re_hwrm_cos2bw_cfg(struct bnxt_re_dev *rdev, u16 target_id, + struct bnxt_re_cos2bw_cfg *cfg); +int bnxt_re_hwrm_pri2cos_cfg(struct bnxt_re_dev *rdev, + u16 target_id, u16 port_id, + u8 *cos_id_map, u8 pri_map); +int bnxt_re_prio_vlan_tx_update(struct bnxt_re_dev *rdev); +int bnxt_re_get_slot_pf_count(struct bnxt_re_dev *rdev); +struct bnxt_re_dev *bnxt_re_get_peer_pf(struct bnxt_re_dev *rdev); +struct bnxt_re_dev *bnxt_re_from_netdev(struct ifnet *netdev); +u8 bnxt_re_get_priority_mask(struct bnxt_re_dev *rdev, u8 selector); +struct bnxt_qplib_nq * bnxt_re_get_nq(struct bnxt_re_dev *rdev); +void bnxt_re_put_nq(struct bnxt_re_dev *rdev, struct bnxt_qplib_nq *nq); + +#define to_bnxt_re(ptr, type, member) \ + container_of(ptr, type, member) + +#define to_bnxt_re_dev(ptr, member) \ + container_of((ptr), struct bnxt_re_dev, member) + +/* Even number functions from port 0 and odd number from port 1 */ +#define BNXT_RE_IS_PORT0(rdev) (!(rdev->en_dev->pdev->devfn & 1)) + +#define BNXT_RE_ROCE_V1_PACKET 0 +#define BNXT_RE_ROCEV2_IPV4_PACKET 2 +#define BNXT_RE_ROCEV2_IPV6_PACKET 3 +#define BNXT_RE_ACTIVE_MAP_PORT1 0x1 /*port-1 active */ +#define BNXT_RE_ACTIVE_MAP_PORT2 0x2 /*port-2 active */ + +#define BNXT_RE_MEMBER_PORT_MAP (BNXT_RE_ACTIVE_MAP_PORT1 | \ + BNXT_RE_ACTIVE_MAP_PORT2) + +#define rdev_to_dev(rdev) ((rdev) ? (&(rdev)->ibdev.dev) : NULL) + +void bnxt_re_set_dma_device(struct ib_device *ibdev, struct bnxt_re_dev *rdev); +bool bnxt_re_is_rdev_valid(struct bnxt_re_dev *rdev); + +#define bnxt_re_rdev_ready(rdev) (bnxt_re_is_rdev_valid(rdev) && \ + (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))) +#define BNXT_RE_SRIOV_CFG_TIMEOUT 6 + +int bnxt_re_get_device_stats(struct bnxt_re_dev *rdev); +void bnxt_re_remove_device(struct bnxt_re_dev *rdev, u8 removal_type, + struct auxiliary_device *aux_dev); +void bnxt_re_destroy_lag(struct bnxt_re_dev **rdev); +int bnxt_re_add_device(struct bnxt_re_dev **rdev, + struct ifnet *netdev, + u8 qp_mode, u8 op_type, u8 wqe_mode, u32 num_msix_requested, + struct auxiliary_device *aux_dev); +void bnxt_re_create_base_interface(bool primary); +int bnxt_re_schedule_work(struct bnxt_re_dev *rdev, unsigned long event, + struct ifnet *vlan_dev, + struct ifnet *netdev, + struct auxiliary_device *aux_dev); +void bnxt_re_get_link_speed(struct bnxt_re_dev *rdev); +int _bnxt_re_ib_init(struct bnxt_re_dev *rdev); +int _bnxt_re_ib_init2(struct bnxt_re_dev *rdev); +void bnxt_re_init_resolve_wq(struct bnxt_re_dev *rdev); +void bnxt_re_uninit_resolve_wq(struct bnxt_re_dev *rdev); + +/* The rdev ref_count is to protect immature removal of the device */ +static inline void bnxt_re_hold(struct bnxt_re_dev *rdev) +{ + atomic_inc(&rdev->ref_count); + dev_dbg(rdev_to_dev(rdev), + "Hold ref_count = 0x%x", atomic_read(&rdev->ref_count)); +} + +static inline void bnxt_re_put(struct bnxt_re_dev *rdev) +{ + atomic_dec(&rdev->ref_count); + dev_dbg(rdev_to_dev(rdev), + "Put ref_count = 0x%x", atomic_read(&rdev->ref_count)); +} + +/* +* Responder Error reason codes +* FIXME: Remove these when the defs +* are properly included in hsi header +*/ +enum res_err_state_reason { + /* No error. */ + CFCQ_RES_ERR_STATE_REASON_NO_ERROR = 0, + /* + * Incoming Send, RDMA write, or RDMA read exceeds the maximum + * transfer length. Detected on RX first and only packets for + * write. Detected on RX request for read. This is an RX + * Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_EXCEED_MAX, + /* + * RDMA write payload size does not match write length. Detected + * when total write payload is not equal to the RDMA write + * length that was given in the first or only packet of the + * request. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_PAYLOAD_LENGTH_MISMATCH, + /* + * Send payload exceeds RQ/SRQ WQE buffer capacity. The total + * send payload that arrived is more than the size of the WQE + * buffer that was fetched from the RQ/SRQ. This is an RX + * Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_EXCEEDS_WQE, + /* + * Responder detected opcode error. * First, only, middle, last + * for incoming requests are improperly ordered with respect to + * previous (PSN) packet. * First or middle packet is not full + * MTU size. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_OPCODE_ERROR, + /* + * PSN sequence error retry limit exceeded. The responder + * encountered a PSN sequence error for the same PSN too many + * times. This can occur via implicit or explicit NAK. This is + * an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_PSN_SEQ_ERROR_RETRY_LIMIT, + /* + * Invalid R_Key. An incoming request contained an R_Key that + * did not reference a valid MR/MW. This error may be detected + * by the RX engine for RDMA write or by the TX engine for RDMA + * read (detected while servicing IRRQ). This is an RX Detected + * Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_RX_INVALID_R_KEY, + /* + * Domain error. An incoming request specified an R_Key which + * referenced a MR/MW that was not in the same PD as the QP on + * which the request arrived. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_RX_DOMAIN_ERROR, + /* + * No permission. An incoming request contained an R_Key that + * referenced a MR/MW which did not have the access permission + * needed for the operation. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_RX_NO_PERMISSION, + /* + * Range error. An incoming request had a combination of R_Key, + * VA, and length that was out of bounds of the associated + * MR/MW. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_RX_RANGE_ERROR, + /* + * Invalid R_Key. An incoming request contained an R_Key that + * did not reference a valid MR/MW. This error may be detected + * by the RX engine for RDMA write or by the TX engine for RDMA + * read (detected while servicing IRRQ). This is a TX Detected + * Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_TX_INVALID_R_KEY, + /* + * Domain error. An incoming request specified an R_Key which + * referenced a MR/MW that was not in the same PD as the QP on + * which the request arrived. This is a TX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_TX_DOMAIN_ERROR, + /* + * No permission. An incoming request contained an R_Key that + * referenced a MR/MW which did not have the access permission + * needed for the operation. This is a TX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_TX_NO_PERMISSION, + /* + * Range error. An incoming request had a combination of R_Key, + * VA, and length that was out of bounds of the associated + * MR/MW. This is a TX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_TX_RANGE_ERROR, + /* + * IRRQ overflow. The peer sent us more RDMA read or atomic + * requests than the negotiated maximum. This is an RX Detected + * Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_IRRQ_OFLOW, + /* + * Unsupported opcode. The peer sent us a request with an opcode + * for a request type that is not supported on this QP. This is + * an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_UNSUPPORTED_OPCODE, + /* + * Unaligned atomic operation. The VA of an atomic request is on + * a memory boundary that prevents atomic execution. This is an + * RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_UNALIGN_ATOMIC, + /* + * Remote invalidate error. A send with invalidate request + * arrived in which the R_Key to invalidate did not describe a + * MR/MW which could be invalidated. RQ WQE completes with error + * status. This error is only reported if the send operation did + * not fail. If the send operation failed then the remote + * invalidate error is not reported. This is an RX Detected + * Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_REM_INVALIDATE, + /* + * Local memory error. An RQ/SRQ SGE described an inaccessible + * memory. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_MEMORY_ERROR, + /* + * SRQ in error. The QP is moving to error state because it + * found SRQ it uses in error. This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_SRQ_ERROR, + /* + * Completion error. No CQE space available on queue or CQ not + * in VALID state. This is a Completion Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_CMP_ERROR, + /* + * Invalid R_Key while resending responses to duplicate request. + * This is a TX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_IVALID_DUP_RKEY, + /* + * Problem was found in the format of a WQE in the RQ/SRQ. This + * is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_WQE_FORMAT_ERROR, + /* + * A load error occurred on an attempt to load the CQ Context. + * This is a Completion Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_CQ_LOAD_ERROR = 0x18, + /* + * A load error occurred on an attempt to load the SRQ Context. + * This is an RX Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_SRQ_LOAD_ERROR, + /* + * A fatal error was detected on an attempt to read from or + * write to PCIe on the transmit side. This error is detected by + * the TX side, but has the priority of a Completion Detected + * Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_TX_PCI_ERROR = 0x1b, + /* + * A fatal error was detected on an attempt to read from or + * write to PCIe on the receive side. This error is detected by + * the RX side (or CAGR), but has the priority of a Completion + * Detected Error. + */ + CFCQ_RES_ERR_STATE_REASON_RES_RX_PCI_ERROR = 0x1c +}; + +int bnxt_re_host_pf_id_query(struct bnxt_re_dev *rdev, + struct bnxt_qplib_query_fn_info *fn_info, + u32 *pf_mask, u32 *first_pf); + +/* Default DCBx and CC values */ +#define BNXT_RE_DEFAULT_CNP_DSCP 48 +#define BNXT_RE_DEFAULT_CNP_PRI 7 +#define BNXT_RE_DEFAULT_ROCE_DSCP 26 +#define BNXT_RE_DEFAULT_ROCE_PRI 3 + +#define BNXT_RE_DEFAULT_L2_BW 50 +#define BNXT_RE_DEFAULT_ROCE_BW 50 + +#define ROCE_PRIO_VALID 0x0 +#define CNP_PRIO_VALID 0x1 +#define ROCE_DSCP_VALID 0x0 +#define CNP_DSCP_VALID 0x1 + +int bnxt_re_get_pri_dscp_settings(struct bnxt_re_dev *rdev, + u16 target_id, + struct bnxt_re_tc_rec *tc_rec); + +int bnxt_re_setup_dscp(struct bnxt_re_dev *rdev); +int bnxt_re_clear_dscp(struct bnxt_re_dev *rdev); +int bnxt_re_setup_cnp_cos(struct bnxt_re_dev *rdev, bool reset); + +static inline enum ib_port_state bnxt_re_get_link_state(struct bnxt_re_dev *rdev) +{ + if (if_getdrvflags(rdev->netdev) & IFF_DRV_RUNNING && + if_getlinkstate(rdev->netdev) == LINK_STATE_UP) + return IB_PORT_ACTIVE; + return IB_PORT_DOWN; +} + +static inline int bnxt_re_link_state(struct bnxt_re_dev *rdev) +{ + return bnxt_re_get_link_state(rdev) == IB_PORT_ACTIVE ? 1:0; +} + +static inline int is_cc_enabled(struct bnxt_re_dev *rdev) +{ + return rdev->cc_param.enable; +} + +static inline void bnxt_re_init_hwrm_hdr(struct bnxt_re_dev *rdev, + struct input *hdr, u16 opcd, + u16 crid, u16 trid) +{ + hdr->req_type = cpu_to_le16(opcd); + hdr->cmpl_ring = cpu_to_le16(crid); + hdr->target_id = cpu_to_le16(trid); +} + +static inline void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, + void *msg, int msg_len, void *resp, + int resp_max_len, int timeout) +{ + fw_msg->msg = msg; + fw_msg->msg_len = msg_len; + fw_msg->resp = resp; + fw_msg->resp_max_len = resp_max_len; + fw_msg->timeout = timeout; +} + +static inline bool is_qport_service_type_supported(struct bnxt_re_dev *rdev) +{ + return rdev->tc_rec[0].serv_type_enabled; +} + +static inline bool is_bnxt_roce_queue(struct bnxt_re_dev *rdev, u8 ser_prof, u8 prof_type) +{ + if (is_qport_service_type_supported(rdev)) + return (prof_type & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_TYPE_ROCE); + else + return (ser_prof == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE); +} + +static inline bool is_bnxt_cnp_queue(struct bnxt_re_dev *rdev, u8 ser_prof, u8 prof_type) +{ + if (is_qport_service_type_supported(rdev)) + return (prof_type & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_TYPE_CNP); + else + return (ser_prof == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP); +} + +#define BNXT_RE_MAP_SH_PAGE 0x0 +#define BNXT_RE_MAP_WC 0x1 +#define BNXT_RE_DBR_PAGE 0x2 +#define BNXT_RE_MAP_DB_RECOVERY_PAGE 0x3 + +#define BNXT_RE_DBR_RECOV_USERLAND_TIMEOUT (20) /* 20 ms */ +#define BNXT_RE_DBR_INT_TIME 5 /* ms */ +#define BNXT_RE_PACING_EN_INT_THRESHOLD 50 /* Entries in DB FIFO */ +#define BNXT_RE_PACING_ALGO_THRESHOLD 250 /* Entries in DB FIFO */ +/* Percentage of DB FIFO depth */ +#define BNXT_RE_PACING_DBQ_THRESHOLD BNXT_RE_PACING_DBQ_HIGH_WATERMARK + +#define BNXT_RE_PACING_ALARM_TH_MULTIPLE(ctx) (_is_chip_p7(ctx) ? 0 : 2) + +/* + * Maximum Percentage of configurable DB FIFO depth. + * The Doorbell FIFO depth is 0x2c00. But the DBR_REG_DB_THROTTLING register has only 12 bits + * to program the high watermark. This means user can configure maximum 36% only(4095/11264). + */ +#define BNXT_RE_PACING_DBQ_HIGH_WATERMARK 36 + +/* Default do_pacing value when there is no congestion */ +#define BNXT_RE_DBR_DO_PACING_NO_CONGESTION 0x7F /* 1 in 512 probability */ + +enum { + BNXT_RE_DBQ_EVENT_SCHED = 0, + BNXT_RE_DBR_PACING_EVENT = 1, + BNXT_RE_DBR_NQ_PACING_NOTIFICATION = 2, +}; + +struct bnxt_re_dbq_work { + struct work_struct work; + struct bnxt_re_dev *rdev; + struct hwrm_async_event_cmpl cmpl; + u32 event; +}; + +int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev); +int bnxt_re_enable_dbr_pacing(struct bnxt_re_dev *rdev); +int bnxt_re_disable_dbr_pacing(struct bnxt_re_dev *rdev); +int bnxt_re_set_dbq_throttling_reg(struct bnxt_re_dev *rdev, + u16 nq_id, u32 throttle); +void bnxt_re_pacing_alert(struct bnxt_re_dev *rdev); +int bnxt_re_hwrm_pri2cos_qcfg(struct bnxt_re_dev *rdev, struct bnxt_re_tc_rec *tc_rec, + u16 target_id); +void writel_fbsd(struct bnxt_softc *bp, u32, u8, u32); +u32 readl_fbsd(struct bnxt_softc *bp, u32, u8); + +static inline unsigned int bnxt_re_get_total_mr_mw_count(struct bnxt_re_dev *rdev) +{ + return (atomic_read(&rdev->stats.rsors.mr_count) + + atomic_read(&rdev->stats.rsors.mw_count)); +} + +static inline void bnxt_re_set_def_pacing_threshold(struct bnxt_re_dev *rdev) +{ + rdev->qplib_res.pacing_data->pacing_th = rdev->pacing_algo_th; + rdev->qplib_res.pacing_data->alarm_th = + rdev->pacing_algo_th * BNXT_RE_PACING_ALARM_TH_MULTIPLE(rdev->chip_ctx); +} + +static inline void bnxt_re_set_def_do_pacing(struct bnxt_re_dev *rdev) +{ + rdev->qplib_res.pacing_data->do_pacing = rdev->dbr_def_do_pacing; +} + +static inline void bnxt_re_set_pacing_dev_state(struct bnxt_re_dev *rdev) +{ + rdev->qplib_res.pacing_data->dev_err_state = + test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); +} +#endif diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.c b/sys/dev/bnxt/bnxt_re/ib_verbs.c new file mode 100644 index 000000000000..0383a16757aa --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/ib_verbs.c @@ -0,0 +1,5498 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: IB Verbs interpreter + */ + +#include <linux/if_ether.h> +#include <linux/etherdevice.h> +#include <rdma/uverbs_ioctl.h> + +#include "bnxt_re.h" +#include "ib_verbs.h" + +static inline +struct scatterlist *get_ib_umem_sgl(struct ib_umem *umem, u32 *nmap) +{ + + *nmap = umem->nmap; + return umem->sg_head.sgl; +} + +static inline void bnxt_re_peer_mem_release(struct ib_umem *umem) +{ + dev_dbg(NULL, "ib_umem_release getting invoked \n"); + ib_umem_release(umem); +} + +void bnxt_re_resolve_dmac_task(struct work_struct *work) +{ + int rc = -1; + struct bnxt_re_dev *rdev; + struct ib_ah_attr *ah_attr; + struct bnxt_re_resolve_dmac_work *dmac_work = + container_of(work, struct bnxt_re_resolve_dmac_work, work); + + rdev = dmac_work->rdev; + ah_attr = dmac_work->ah_attr; + rc = ib_resolve_eth_dmac(&rdev->ibdev, ah_attr); + if (rc) + dev_err(rdev_to_dev(dmac_work->rdev), + "Failed to resolve dest mac rc = %d\n", rc); + atomic_set(&dmac_work->status_wait, rc << 8); +} + +static int __from_ib_access_flags(int iflags) +{ + int qflags = 0; + + if (iflags & IB_ACCESS_LOCAL_WRITE) + qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE; + if (iflags & IB_ACCESS_REMOTE_READ) + qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ; + if (iflags & IB_ACCESS_REMOTE_WRITE) + qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE; + if (iflags & IB_ACCESS_REMOTE_ATOMIC) + qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC; + if (iflags & IB_ACCESS_MW_BIND) + qflags |= BNXT_QPLIB_ACCESS_MW_BIND; + if (iflags & IB_ZERO_BASED) + qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED; + if (iflags & IB_ACCESS_ON_DEMAND) + qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND; + return qflags; +}; + +static enum ib_access_flags __to_ib_access_flags(int qflags) +{ + enum ib_access_flags iflags = 0; + + if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE) + iflags |= IB_ACCESS_LOCAL_WRITE; + if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE) + iflags |= IB_ACCESS_REMOTE_WRITE; + if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ) + iflags |= IB_ACCESS_REMOTE_READ; + if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC) + iflags |= IB_ACCESS_REMOTE_ATOMIC; + if (qflags & BNXT_QPLIB_ACCESS_MW_BIND) + iflags |= IB_ACCESS_MW_BIND; + if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED) + iflags |= IB_ZERO_BASED; + if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND) + iflags |= IB_ACCESS_ON_DEMAND; + return iflags; +}; + +static int bnxt_re_copy_to_udata(struct bnxt_re_dev *rdev, void *data, + int len, struct ib_udata *udata) +{ + int rc; + + rc = ib_copy_to_udata(udata, data, len); + if (rc) + dev_err(rdev_to_dev(rdev), + "ucontext copy failed from %ps rc %d\n", + __builtin_return_address(0), rc); + + return rc; +} + +struct ifnet *bnxt_re_get_netdev(struct ib_device *ibdev, + u8 port_num) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct ifnet *netdev = NULL; + + rcu_read_lock(); + + if (!rdev || !rdev->netdev) + goto end; + + netdev = rdev->netdev; + + /* In case of active-backup bond mode, return active slave */ + if (netdev) + dev_hold(netdev); + +end: + rcu_read_unlock(); + return netdev; +} + +int bnxt_re_query_device(struct ib_device *ibdev, + struct ib_device_attr *ib_attr, + struct ib_udata *udata) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr; + + memset(ib_attr, 0, sizeof(*ib_attr)); + + memcpy(&ib_attr->fw_ver, dev_attr->fw_ver, 4); + bnxt_qplib_get_guid(rdev->dev_addr, (u8 *)&ib_attr->sys_image_guid); + ib_attr->max_mr_size = BNXT_RE_MAX_MR_SIZE; + ib_attr->page_size_cap = dev_attr->page_size_cap; + ib_attr->vendor_id = rdev->en_dev->pdev->vendor; + ib_attr->vendor_part_id = rdev->en_dev->pdev->device; + ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device; + ib_attr->max_qp = dev_attr->max_qp; + ib_attr->max_qp_wr = dev_attr->max_qp_wqes; + /* + * Read and set from the module param 'min_tx_depth' + * only once after the driver load + */ + if (rdev->min_tx_depth == 1 && + min_tx_depth < dev_attr->max_qp_wqes) + rdev->min_tx_depth = min_tx_depth; + ib_attr->device_cap_flags = + IB_DEVICE_CURR_QP_STATE_MOD + | IB_DEVICE_RC_RNR_NAK_GEN + | IB_DEVICE_SHUTDOWN_PORT + | IB_DEVICE_SYS_IMAGE_GUID + | IB_DEVICE_LOCAL_DMA_LKEY + | IB_DEVICE_RESIZE_MAX_WR + | IB_DEVICE_PORT_ACTIVE_EVENT + | IB_DEVICE_N_NOTIFY_CQ + | IB_DEVICE_MEM_WINDOW + | IB_DEVICE_MEM_WINDOW_TYPE_2B + | IB_DEVICE_MEM_MGT_EXTENSIONS; + ib_attr->max_send_sge = dev_attr->max_qp_sges; + ib_attr->max_recv_sge = dev_attr->max_qp_sges; + ib_attr->max_sge_rd = dev_attr->max_qp_sges; + ib_attr->max_cq = dev_attr->max_cq; + ib_attr->max_cqe = dev_attr->max_cq_wqes; + ib_attr->max_mr = dev_attr->max_mr; + ib_attr->max_pd = dev_attr->max_pd; + ib_attr->max_qp_rd_atom = dev_attr->max_qp_rd_atom; + ib_attr->max_qp_init_rd_atom = dev_attr->max_qp_init_rd_atom; + if (dev_attr->is_atomic) { + ib_attr->atomic_cap = IB_ATOMIC_GLOB; + ib_attr->masked_atomic_cap = IB_ATOMIC_GLOB; + } + ib_attr->max_ee_rd_atom = 0; + ib_attr->max_res_rd_atom = 0; + ib_attr->max_ee_init_rd_atom = 0; + ib_attr->max_ee = 0; + ib_attr->max_rdd = 0; + ib_attr->max_mw = dev_attr->max_mw; + ib_attr->max_raw_ipv6_qp = 0; + ib_attr->max_raw_ethy_qp = dev_attr->max_raw_ethy_qp; + ib_attr->max_mcast_grp = 0; + ib_attr->max_mcast_qp_attach = 0; + ib_attr->max_total_mcast_qp_attach = 0; + ib_attr->max_ah = dev_attr->max_ah; + ib_attr->max_srq = dev_attr->max_srq; + ib_attr->max_srq_wr = dev_attr->max_srq_wqes; + ib_attr->max_srq_sge = dev_attr->max_srq_sges; + + ib_attr->max_fast_reg_page_list_len = MAX_PBL_LVL_1_PGS; + ib_attr->max_pkeys = 1; + ib_attr->local_ca_ack_delay = BNXT_RE_DEFAULT_ACK_DELAY; + ib_attr->sig_prot_cap = 0; + ib_attr->sig_guard_cap = 0; + ib_attr->odp_caps.general_caps = 0; + + return 0; +} + +int bnxt_re_modify_device(struct ib_device *ibdev, + int device_modify_mask, + struct ib_device_modify *device_modify) +{ + dev_dbg(rdev_to_dev(rdev), "Modify device with mask 0x%x\n", + device_modify_mask); + + switch (device_modify_mask) { + case IB_DEVICE_MODIFY_SYS_IMAGE_GUID: + /* Modify the GUID requires the modification of the GID table */ + /* GUID should be made as READ-ONLY */ + break; + case IB_DEVICE_MODIFY_NODE_DESC: + /* Node Desc should be made as READ-ONLY */ + break; + default: + break; + } + return 0; +} + +static void __to_ib_speed_width(u32 espeed, u8 *speed, u8 *width) +{ + switch (espeed) { + case SPEED_1000: + *speed = IB_SPEED_SDR; + *width = IB_WIDTH_1X; + break; + case SPEED_10000: + *speed = IB_SPEED_QDR; + *width = IB_WIDTH_1X; + break; + case SPEED_20000: + *speed = IB_SPEED_DDR; + *width = IB_WIDTH_4X; + break; + case SPEED_25000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_1X; + break; + case SPEED_40000: + *speed = IB_SPEED_QDR; + *width = IB_WIDTH_4X; + break; + case SPEED_50000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_2X; + break; + case SPEED_100000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_4X; + break; + case SPEED_200000: + *speed = IB_SPEED_HDR; + *width = IB_WIDTH_4X; + break; + default: + *speed = IB_SPEED_SDR; + *width = IB_WIDTH_1X; + break; + } +} + +/* Port */ +int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num, + struct ib_port_attr *port_attr) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr; + u8 active_speed = 0, active_width = 0; + + dev_dbg(rdev_to_dev(rdev), "QUERY PORT with port_num 0x%x\n", port_num); + memset(port_attr, 0, sizeof(*port_attr)); + + port_attr->phys_state = IB_PORT_PHYS_STATE_DISABLED; + port_attr->state = bnxt_re_get_link_state(rdev); + if (port_attr->state == IB_PORT_ACTIVE) + port_attr->phys_state = IB_PORT_PHYS_STATE_LINK_UP; + port_attr->max_mtu = IB_MTU_4096; + port_attr->active_mtu = iboe_get_mtu(if_getmtu(rdev->netdev)); + port_attr->gid_tbl_len = dev_attr->max_sgid; + port_attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP | + IB_PORT_DEVICE_MGMT_SUP | + IB_PORT_VENDOR_CLASS_SUP | + IB_PORT_IP_BASED_GIDS; + + port_attr->max_msg_sz = (u32)BNXT_RE_MAX_MR_SIZE_LOW; + port_attr->bad_pkey_cntr = 0; + port_attr->qkey_viol_cntr = 0; + port_attr->pkey_tbl_len = dev_attr->max_pkey; + port_attr->lid = 0; + port_attr->sm_lid = 0; + port_attr->lmc = 0; + port_attr->max_vl_num = 4; + port_attr->sm_sl = 0; + port_attr->subnet_timeout = 0; + port_attr->init_type_reply = 0; + rdev->espeed = rdev->en_dev->espeed; + + if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) + __to_ib_speed_width(rdev->espeed, &active_speed, + &active_width); + + port_attr->active_speed = active_speed; + port_attr->active_width = active_width; + + return 0; +} + +int bnxt_re_modify_port(struct ib_device *ibdev, u8 port_num, + int port_modify_mask, + struct ib_port_modify *port_modify) +{ + dev_dbg(rdev_to_dev(rdev), "Modify port with mask 0x%x\n", + port_modify_mask); + + switch (port_modify_mask) { + case IB_PORT_SHUTDOWN: + break; + case IB_PORT_INIT_TYPE: + break; + case IB_PORT_RESET_QKEY_CNTR: + break; + default: + break; + } + return 0; +} + +int bnxt_re_get_port_immutable(struct ib_device *ibdev, u8 port_num, + struct ib_port_immutable *immutable) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct ib_port_attr port_attr; + + if (bnxt_re_query_port(ibdev, port_num, &port_attr)) + return -EINVAL; + + immutable->pkey_tbl_len = port_attr.pkey_tbl_len; + immutable->gid_tbl_len = port_attr.gid_tbl_len; + if (rdev->roce_mode == BNXT_RE_FLAG_ROCEV1_CAP) + immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE; + else if (rdev->roce_mode == BNXT_RE_FLAG_ROCEV2_CAP) + immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP; + else + immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE | + RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP; + immutable->max_mad_size = IB_MGMT_MAD_SIZE; + return 0; +} + +void bnxt_re_compat_qfwstr(void) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + + sprintf(str, "%d.%d.%d.%d", rdev->dev_attr->fw_ver[0], + rdev->dev_attr->fw_ver[1], rdev->dev_attr->fw_ver[2], + rdev->dev_attr->fw_ver[3]); +} + +int bnxt_re_query_pkey(struct ib_device *ibdev, u8 port_num, + u16 index, u16 *pkey) +{ + if (index > 0) + return -EINVAL; + + *pkey = IB_DEFAULT_PKEY_FULL; + + return 0; +} + +int bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num, + int index, union ib_gid *gid) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + int rc = 0; + + /* Ignore port_num */ + memset(gid, 0, sizeof(*gid)); + rc = bnxt_qplib_get_sgid(&rdev->qplib_res, + &rdev->qplib_res.sgid_tbl, index, + (struct bnxt_qplib_gid *)gid); + return rc; +} + +int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num, + unsigned int index, void **context) +{ + int rc = 0; + struct bnxt_re_gid_ctx *ctx, **ctx_tbl; + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; + struct bnxt_qplib_gid *gid_to_del; + u16 vlan_id = 0xFFFF; + + /* Delete the entry from the hardware */ + ctx = *context; + if (!ctx) { + dev_err(rdev_to_dev(rdev), "GID entry has no ctx?!\n"); + return -EINVAL; + } + if (sgid_tbl && sgid_tbl->active) { + if (ctx->idx >= sgid_tbl->max) { + dev_dbg(rdev_to_dev(rdev), "GID index out of range?!\n"); + return -EINVAL; + } + gid_to_del = &sgid_tbl->tbl[ctx->idx].gid; + vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id; + ctx->refcnt--; + /* DEL_GID is called via WQ context(netdevice_event_work_handler) + * or via the ib_unregister_device path. In the former case QP1 + * may not be destroyed yet, in which case just return as FW + * needs that entry to be present and will fail it's deletion. + * We could get invoked again after QP1 is destroyed OR get an + * ADD_GID call with a different GID value for the same index + * where we issue MODIFY_GID cmd to update the GID entry -- TBD + */ + if (ctx->idx == 0 && + rdma_link_local_addr((struct in6_addr *)gid_to_del) && + (rdev->gsi_ctx.gsi_sqp || + rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_UD)) { + dev_dbg(rdev_to_dev(rdev), + "Trying to delete GID0 while QP1 is alive\n"); + if (!ctx->refcnt) { + rdev->gid_map[index] = -1; + ctx_tbl = sgid_tbl->ctx; + ctx_tbl[ctx->idx] = NULL; + kfree(ctx); + } + return 0; + } + rdev->gid_map[index] = -1; + if (!ctx->refcnt) { + rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del, + vlan_id, true); + if (!rc) { + dev_dbg(rdev_to_dev(rdev), "GID remove success\n"); + ctx_tbl = sgid_tbl->ctx; + ctx_tbl[ctx->idx] = NULL; + kfree(ctx); + } else { + dev_err(rdev_to_dev(rdev), + "Remove GID failed rc = 0x%x\n", rc); + } + } + } else { + dev_dbg(rdev_to_dev(rdev), "GID sgid_tbl does not exist!\n"); + return -EINVAL; + } + return rc; +} + +int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num, + unsigned int index, const union ib_gid *gid, + const struct ib_gid_attr *attr, void **context) +{ + int rc; + u32 tbl_idx = 0; + u16 vlan_id = 0xFFFF; + struct bnxt_re_gid_ctx *ctx, **ctx_tbl; + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; + if ((attr->ndev) && is_vlan_dev(attr->ndev)) + vlan_id = vlan_dev_vlan_id(attr->ndev); + + rc = bnxt_qplib_add_sgid(sgid_tbl, gid, + rdev->dev_addr, + vlan_id, true, &tbl_idx); + if (rc == -EALREADY) { + dev_dbg(rdev_to_dev(rdev), "GID %pI6 is already present\n", gid); + ctx_tbl = sgid_tbl->ctx; + if (!ctx_tbl[tbl_idx]) { + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->idx = tbl_idx; + ctx->refcnt = 1; + ctx_tbl[tbl_idx] = ctx; + } else { + ctx_tbl[tbl_idx]->refcnt++; + } + *context = ctx_tbl[tbl_idx]; + /* tbl_idx is the HW table index and index is the stack index */ + rdev->gid_map[index] = tbl_idx; + return 0; + } else if (rc < 0) { + dev_err(rdev_to_dev(rdev), "Add GID failed rc = 0x%x\n", rc); + return rc; + } else { + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + dev_err(rdev_to_dev(rdev), "Add GID ctx failed\n"); + return -ENOMEM; + } + ctx_tbl = sgid_tbl->ctx; + ctx->idx = tbl_idx; + ctx->refcnt = 1; + ctx_tbl[tbl_idx] = ctx; + /* tbl_idx is the HW table index and index is the stack index */ + rdev->gid_map[index] = tbl_idx; + *context = ctx; + } + return rc; +} + +enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev, + u8 port_num) +{ + return IB_LINK_LAYER_ETHERNET; +} + +static void bnxt_re_legacy_create_fence_wqe(struct bnxt_re_pd *pd) +{ + struct bnxt_re_legacy_fence_data *fence = &pd->fence; + struct ib_mr *ib_mr = &fence->mr->ib_mr; + struct bnxt_qplib_swqe *wqe = &fence->bind_wqe; + struct bnxt_re_dev *rdev = pd->rdev; + + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + return; + + memset(wqe, 0, sizeof(*wqe)); + wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW; + wqe->wr_id = BNXT_QPLIB_FENCE_WRID; + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; + wqe->bind.zero_based = false; + wqe->bind.parent_l_key = ib_mr->lkey; + wqe->bind.va = (u64)fence->va; + wqe->bind.length = fence->size; + wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ); + wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1; + + /* Save the initial rkey in fence structure for now; + * wqe->bind.r_key will be set at (re)bind time. + */ + fence->bind_rkey = ib_inc_rkey(fence->mw->rkey); +} + +static int bnxt_re_legacy_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp) +{ + struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp, + qplib_qp); + struct ib_pd *ib_pd = qp->ib_qp.pd; + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_legacy_fence_data *fence = &pd->fence; + struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe; + struct bnxt_qplib_swqe wqe; + int rc; + + /* TODO: Need SQ locking here when Fence WQE + * posting moves up into bnxt_re from bnxt_qplib. + */ + memcpy(&wqe, fence_wqe, sizeof(wqe)); + wqe.bind.r_key = fence->bind_rkey; + fence->bind_rkey = ib_inc_rkey(fence->bind_rkey); + + dev_dbg(rdev_to_dev(qp->rdev), + "Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n", + wqe.bind.r_key, qp->qplib_qp.id, pd); + rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe); + if (rc) { + dev_err(rdev_to_dev(qp->rdev), "Failed to bind fence-WQE\n"); + return rc; + } + bnxt_qplib_post_send_db(&qp->qplib_qp); + + return rc; +} + +static int bnxt_re_legacy_create_fence_mr(struct bnxt_re_pd *pd) +{ + int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND; + struct bnxt_re_legacy_fence_data *fence = &pd->fence; + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_qplib_mrinfo mrinfo; + struct bnxt_re_mr *mr = NULL; + struct ib_mw *ib_mw = NULL; + dma_addr_t dma_addr = 0; + u32 max_mr_count; + u64 pbl_tbl; + int rc; + + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + return 0; + + memset(&mrinfo, 0, sizeof(mrinfo)); + /* Allocate a small chunk of memory and dma-map it */ + fence->va = kzalloc(BNXT_RE_LEGACY_FENCE_BYTES, GFP_KERNEL); + if (!fence->va) + return -ENOMEM; + dma_addr = ib_dma_map_single(&rdev->ibdev, fence->va, + BNXT_RE_LEGACY_FENCE_BYTES, + DMA_BIDIRECTIONAL); + rc = ib_dma_mapping_error(&rdev->ibdev, dma_addr); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to dma-map fence-MR-mem\n"); + rc = -EIO; + fence->dma_addr = 0; + goto free_va; + } + fence->dma_addr = dma_addr; + + /* Allocate a MR */ + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) + goto free_dma_addr; + fence->mr = mr; + mr->rdev = rdev; + mr->qplib_mr.pd = &pd->qplib_pd; + mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR; + mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags); + if (!_is_alloc_mr_unified(rdev->qplib_res.dattr)) { + rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to alloc fence-HW-MR\n"); + goto free_mr; + } + /* Register MR */ + mr->ib_mr.lkey = mr->qplib_mr.lkey; + } + mr->qplib_mr.va = (u64)fence->va; + mr->qplib_mr.total_size = BNXT_RE_LEGACY_FENCE_BYTES; + pbl_tbl = dma_addr; + + mrinfo.mrw = &mr->qplib_mr; + mrinfo.ptes = &pbl_tbl; + mrinfo.sg.npages = BNXT_RE_LEGACY_FENCE_PBL_SIZE; + + mrinfo.sg.nmap = 0; + mrinfo.sg.sghead = 0; + mrinfo.sg.pgshft = PAGE_SHIFT; + mrinfo.sg.pgsize = PAGE_SIZE; + rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mrinfo, false); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to register fence-MR\n"); + goto free_mr; + } + mr->ib_mr.lkey = mr->qplib_mr.lkey; + mr->ib_mr.rkey = mr->qplib_mr.rkey; + atomic_inc(&rdev->stats.rsors.mr_count); + max_mr_count = atomic_read(&rdev->stats.rsors.mr_count); + if (max_mr_count > (atomic_read(&rdev->stats.rsors.max_mr_count))) + atomic_set(&rdev->stats.rsors.max_mr_count, max_mr_count); + + ib_mw = bnxt_re_alloc_mw(&pd->ibpd, IB_MW_TYPE_1, NULL); + /* Create a fence MW only for kernel consumers */ + if (!ib_mw) { + dev_err(rdev_to_dev(rdev), + "Failed to create fence-MW for PD: %p\n", pd); + rc = -EINVAL; + goto free_mr; + } + fence->mw = ib_mw; + + bnxt_re_legacy_create_fence_wqe(pd); + return 0; + +free_mr: + if (mr->ib_mr.lkey) { + bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); + atomic_dec(&rdev->stats.rsors.mr_count); + } + kfree(mr); + fence->mr = NULL; + +free_dma_addr: + ib_dma_unmap_single(&rdev->ibdev, fence->dma_addr, + BNXT_RE_LEGACY_FENCE_BYTES, DMA_BIDIRECTIONAL); + fence->dma_addr = 0; + +free_va: + kfree(fence->va); + fence->va = NULL; + return rc; +} + +static void bnxt_re_legacy_destroy_fence_mr(struct bnxt_re_pd *pd) +{ + struct bnxt_re_legacy_fence_data *fence = &pd->fence; + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_mr *mr = fence->mr; + + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + return; + + if (fence->mw) { + bnxt_re_dealloc_mw(fence->mw); + fence->mw = NULL; + } + if (mr) { + if (mr->ib_mr.rkey) + bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr, + false); + if (mr->ib_mr.lkey) + bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); + kfree(mr); + fence->mr = NULL; + atomic_dec(&rdev->stats.rsors.mr_count); + } + if (fence->dma_addr) { + ib_dma_unmap_single(&rdev->ibdev, fence->dma_addr, + BNXT_RE_LEGACY_FENCE_BYTES, + DMA_BIDIRECTIONAL); + fence->dma_addr = 0; + } + kfree(fence->va); + fence->va = NULL; +} + + +static int bnxt_re_get_user_dpi(struct bnxt_re_dev *rdev, + struct bnxt_re_ucontext *cntx) +{ + struct bnxt_qplib_chip_ctx *cctx = rdev->chip_ctx; + int ret = 0; + u8 type; + /* Allocate DPI in alloc_pd or in create_cq to avoid failing of + * ibv_devinfo and family of application when DPIs are depleted. + */ + type = BNXT_QPLIB_DPI_TYPE_UC; + ret = bnxt_qplib_alloc_dpi(&rdev->qplib_res, &cntx->dpi, cntx, type); + if (ret) { + dev_err(rdev_to_dev(rdev), "Alloc doorbell page failed!\n"); + goto out; + } + + if (cctx->modes.db_push) { + type = BNXT_QPLIB_DPI_TYPE_WC; + ret = bnxt_qplib_alloc_dpi(&rdev->qplib_res, &cntx->wcdpi, + cntx, type); + if (ret) + dev_err(rdev_to_dev(rdev), "push dp alloc failed\n"); + } +out: + return ret; +} + +/* Protection Domains */ +void bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata) +{ + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_dev *rdev = pd->rdev; + int rc; + + bnxt_re_legacy_destroy_fence_mr(pd); + + rc = bnxt_qplib_dealloc_pd(&rdev->qplib_res, + &rdev->qplib_res.pd_tbl, + &pd->qplib_pd); + if (rc) + dev_err_ratelimited(rdev_to_dev(rdev), + "%s failed rc = %d\n", __func__, rc); + atomic_dec(&rdev->stats.rsors.pd_count); + + return; +} + +int bnxt_re_alloc_pd(struct ib_pd *pd_in, + struct ib_udata *udata) +{ + struct ib_pd *ibpd = pd_in; + struct ib_device *ibdev = ibpd->device; + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_re_ucontext *ucntx = + rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, + ibucontext); + u32 max_pd_count; + int rc; + struct bnxt_re_pd *pd = container_of(ibpd, struct bnxt_re_pd, ibpd); + + pd->rdev = rdev; + if (bnxt_qplib_alloc_pd(&rdev->qplib_res, &pd->qplib_pd)) { + dev_err(rdev_to_dev(rdev), + "Allocate HW Protection Domain failed!\n"); + rc = -ENOMEM; + goto fail; + } + + if (udata) { + struct bnxt_re_pd_resp resp = {}; + + if (!ucntx->dpi.dbr) { + rc = bnxt_re_get_user_dpi(rdev, ucntx); + if (rc) + goto dbfail; + } + + resp.pdid = pd->qplib_pd.id; + /* Still allow mapping this DBR to the new user PD. */ + resp.dpi = ucntx->dpi.dpi; + resp.dbr = (u64)ucntx->dpi.umdbr; + /* Copy only on a valid wcpdi */ + if (ucntx->wcdpi.dpi) { + resp.wcdpi = ucntx->wcdpi.dpi; + resp.comp_mask = BNXT_RE_COMP_MASK_PD_HAS_WC_DPI; + } + if (rdev->dbr_pacing) { + WARN_ON(!rdev->dbr_bar_addr); + resp.dbr_bar_addr = (u64)rdev->dbr_bar_addr; + resp.comp_mask |= BNXT_RE_COMP_MASK_PD_HAS_DBR_BAR_ADDR; + } + + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) + goto dbfail; + } + + if (!udata) + if (bnxt_re_legacy_create_fence_mr(pd)) + dev_warn(rdev_to_dev(rdev), + "Failed to create Fence-MR\n"); + + atomic_inc(&rdev->stats.rsors.pd_count); + max_pd_count = atomic_read(&rdev->stats.rsors.pd_count); + if (max_pd_count > atomic_read(&rdev->stats.rsors.max_pd_count)) + atomic_set(&rdev->stats.rsors.max_pd_count, max_pd_count); + + return 0; +dbfail: + (void)bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl, + &pd->qplib_pd); +fail: + return rc; +} + +/* Address Handles */ +void bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags) +{ + struct bnxt_re_ah *ah = to_bnxt_re(ib_ah, struct bnxt_re_ah, ibah); + struct bnxt_re_dev *rdev = ah->rdev; + int rc = 0; + bool block = true; + + block = !(flags & RDMA_DESTROY_AH_SLEEPABLE); + + rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah, block); + if (rc) + dev_err_ratelimited(rdev_to_dev(rdev), + "%s id = %d blocking %d failed rc = %d\n", + __func__, ah->qplib_ah.id, block, rc); + atomic_dec(&rdev->stats.rsors.ah_count); + + return; +} + +static u8 _to_bnxt_re_nw_type(enum rdma_network_type ntype) +{ + u8 nw_type; + switch (ntype) { + case RDMA_NETWORK_IPV4: + nw_type = CMDQ_CREATE_AH_TYPE_V2IPV4; + break; + case RDMA_NETWORK_IPV6: + nw_type = CMDQ_CREATE_AH_TYPE_V2IPV6; + break; + default: + nw_type = CMDQ_CREATE_AH_TYPE_V1; + break; + } + return nw_type; +} + +static inline int +bnxt_re_get_cached_gid(struct ib_device *dev, u8 port_num, int index, + union ib_gid *sgid, struct ib_gid_attr **sgid_attr, + struct ib_global_route *grh, struct ib_ah *ah) +{ + int ret = 0; + + ret = ib_get_cached_gid(dev, port_num, index, sgid, *sgid_attr); + return ret; +} + +static inline enum rdma_network_type +bnxt_re_gid_to_network_type(struct ib_gid_attr *sgid_attr, + union ib_gid *sgid) +{ + return ib_gid_to_network_type(sgid_attr->gid_type, sgid); +} + +static int bnxt_re_get_ah_info(struct bnxt_re_dev *rdev, + struct ib_ah_attr *ah_attr, + struct bnxt_re_ah_info *ah_info) +{ + struct ib_gid_attr *gattr; + enum rdma_network_type ib_ntype; + u8 ntype; + union ib_gid *gid; + int rc = 0; + + gid = &ah_info->sgid; + gattr = &ah_info->sgid_attr; + + rc = bnxt_re_get_cached_gid(&rdev->ibdev, 1, ah_attr->grh.sgid_index, + gid, &gattr, &ah_attr->grh, NULL); + if (rc) + return rc; + + /* Get vlan tag */ + if (gattr->ndev) { + if (is_vlan_dev(gattr->ndev)) + ah_info->vlan_tag = vlan_dev_vlan_id(gattr->ndev); + if_rele(gattr->ndev); + } + + /* Get network header type for this GID */ + + ib_ntype = bnxt_re_gid_to_network_type(gattr, gid); + ntype = _to_bnxt_re_nw_type(ib_ntype); + ah_info->nw_type = ntype; + + return rc; +} + +static u8 _get_sgid_index(struct bnxt_re_dev *rdev, u8 gindx) +{ + gindx = rdev->gid_map[gindx]; + return gindx; +} + +static int bnxt_re_init_dmac(struct bnxt_re_dev *rdev, struct ib_ah_attr *ah_attr, + struct bnxt_re_ah_info *ah_info, bool is_user, + struct bnxt_re_ah *ah) +{ + int rc = 0; + u8 *dmac; + + if (is_user && !rdma_is_multicast_addr((struct in6_addr *) + ah_attr->grh.dgid.raw) && + !rdma_link_local_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) { + + u32 retry_count = BNXT_RE_RESOLVE_RETRY_COUNT_US; + struct bnxt_re_resolve_dmac_work *resolve_dmac_work; + + + resolve_dmac_work = kzalloc(sizeof(*resolve_dmac_work), GFP_ATOMIC); + + resolve_dmac_work->rdev = rdev; + resolve_dmac_work->ah_attr = ah_attr; + resolve_dmac_work->ah_info = ah_info; + + atomic_set(&resolve_dmac_work->status_wait, 1); + INIT_WORK(&resolve_dmac_work->work, bnxt_re_resolve_dmac_task); + queue_work(rdev->resolve_wq, &resolve_dmac_work->work); + + do { + rc = atomic_read(&resolve_dmac_work->status_wait) & 0xFF; + if (!rc) + break; + udelay(1); + } while (--retry_count); + if (atomic_read(&resolve_dmac_work->status_wait)) { + INIT_LIST_HEAD(&resolve_dmac_work->list); + list_add_tail(&resolve_dmac_work->list, + &rdev->mac_wq_list); + return -EFAULT; + } + kfree(resolve_dmac_work); + } + dmac = ROCE_DMAC(ah_attr); + if (dmac) + memcpy(ah->qplib_ah.dmac, dmac, ETH_ALEN); + return rc; +} + +int bnxt_re_create_ah(struct ib_ah *ah_in, struct ib_ah_attr *attr, + u32 flags, struct ib_udata *udata) +{ + + struct ib_ah *ib_ah = ah_in; + struct ib_pd *ib_pd = ib_ah->pd; + struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ibah); + struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_ah_info ah_info; + u32 max_ah_count; + bool is_user; + int rc; + bool block = true; + struct ib_ah_attr *ah_attr = attr; + block = !(flags & RDMA_CREATE_AH_SLEEPABLE); + + if (!(ah_attr->ah_flags & IB_AH_GRH)) + dev_err(rdev_to_dev(rdev), "ah_attr->ah_flags GRH is not set\n"); + + ah->rdev = rdev; + ah->qplib_ah.pd = &pd->qplib_pd; + is_user = ib_pd->uobject ? true : false; + + /* Supply the configuration for the HW */ + memcpy(ah->qplib_ah.dgid.data, ah_attr->grh.dgid.raw, + sizeof(union ib_gid)); + ah->qplib_ah.sgid_index = _get_sgid_index(rdev, ah_attr->grh.sgid_index); + if (ah->qplib_ah.sgid_index == 0xFF) { + dev_err(rdev_to_dev(rdev), "invalid sgid_index!\n"); + rc = -EINVAL; + goto fail; + } + ah->qplib_ah.host_sgid_index = ah_attr->grh.sgid_index; + ah->qplib_ah.traffic_class = ah_attr->grh.traffic_class; + ah->qplib_ah.flow_label = ah_attr->grh.flow_label; + ah->qplib_ah.hop_limit = ah_attr->grh.hop_limit; + ah->qplib_ah.sl = ah_attr->sl; + rc = bnxt_re_get_ah_info(rdev, ah_attr, &ah_info); + if (rc) + goto fail; + ah->qplib_ah.nw_type = ah_info.nw_type; + + rc = bnxt_re_init_dmac(rdev, ah_attr, &ah_info, is_user, ah); + if (rc) + goto fail; + + rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah, block); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Allocate HW Address Handle failed!\n"); + goto fail; + } + + /* Write AVID to shared page. */ + if (ib_pd->uobject) { + struct ib_ucontext *ib_uctx = ib_pd->uobject->context; + struct bnxt_re_ucontext *uctx; + unsigned long flag; + u32 *wrptr; + + uctx = to_bnxt_re(ib_uctx, struct bnxt_re_ucontext, ibucontext); + spin_lock_irqsave(&uctx->sh_lock, flag); + wrptr = (u32 *)((u8 *)uctx->shpg + BNXT_RE_AVID_OFFT); + *wrptr = ah->qplib_ah.id; + wmb(); /* make sure cache is updated. */ + spin_unlock_irqrestore(&uctx->sh_lock, flag); + } + atomic_inc(&rdev->stats.rsors.ah_count); + max_ah_count = atomic_read(&rdev->stats.rsors.ah_count); + if (max_ah_count > atomic_read(&rdev->stats.rsors.max_ah_count)) + atomic_set(&rdev->stats.rsors.max_ah_count, max_ah_count); + + return 0; +fail: + return rc; +} + +int bnxt_re_modify_ah(struct ib_ah *ib_ah, struct ib_ah_attr *ah_attr) +{ + return 0; +} + +int bnxt_re_query_ah(struct ib_ah *ib_ah, struct ib_ah_attr *ah_attr) +{ + struct bnxt_re_ah *ah = to_bnxt_re(ib_ah, struct bnxt_re_ah, ibah); + + memcpy(ah_attr->grh.dgid.raw, ah->qplib_ah.dgid.data, + sizeof(union ib_gid)); + ah_attr->grh.sgid_index = ah->qplib_ah.host_sgid_index; + ah_attr->grh.traffic_class = ah->qplib_ah.traffic_class; + ah_attr->sl = ah->qplib_ah.sl; + memcpy(ROCE_DMAC(ah_attr), ah->qplib_ah.dmac, ETH_ALEN); + ah_attr->ah_flags = IB_AH_GRH; + ah_attr->port_num = 1; + ah_attr->static_rate = 0; + + return 0; +} + +/* Shared Receive Queues */ +void bnxt_re_destroy_srq(struct ib_srq *ib_srq, + struct ib_udata *udata) +{ + struct bnxt_re_srq *srq = to_bnxt_re(ib_srq, struct bnxt_re_srq, ibsrq); + struct bnxt_re_dev *rdev = srq->rdev; + struct bnxt_qplib_srq *qplib_srq = &srq->qplib_srq; + int rc = 0; + + + rc = bnxt_qplib_destroy_srq(&rdev->qplib_res, qplib_srq); + if (rc) + dev_err_ratelimited(rdev_to_dev(rdev), + "%s id = %d failed rc = %d\n", + __func__, qplib_srq->id, rc); + + if (srq->umem && !IS_ERR(srq->umem)) + ib_umem_release(srq->umem); + + atomic_dec(&rdev->stats.rsors.srq_count); + + return; +} + +static u16 _max_rwqe_sz(int nsge) +{ + return sizeof(struct rq_wqe_hdr) + (nsge * sizeof(struct sq_sge)); +} + +static u16 bnxt_re_get_rwqe_size(struct bnxt_qplib_qp *qplqp, + int rsge, int max) +{ + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + rsge = max; + + return _max_rwqe_sz(rsge); +} + +static inline +struct ib_umem *ib_umem_get_compat(struct bnxt_re_dev *rdev, + struct ib_ucontext *ucontext, + struct ib_udata *udata, + unsigned long addr, + size_t size, int access, int dmasync) +{ + return ib_umem_get(ucontext, addr, size, access, dmasync); +} + +static inline +struct ib_umem *ib_umem_get_flags_compat(struct bnxt_re_dev *rdev, + struct ib_ucontext *ucontext, + struct ib_udata *udata, + unsigned long addr, + size_t size, int access, int dmasync) +{ + return ib_umem_get_compat(rdev, ucontext, udata, addr, size, + access, 0); +} + +static inline size_t ib_umem_num_pages_compat(struct ib_umem *umem) +{ + return ib_umem_num_pages(umem); +} + +static int bnxt_re_init_user_srq(struct bnxt_re_dev *rdev, + struct bnxt_re_pd *pd, + struct bnxt_re_srq *srq, + struct ib_udata *udata) +{ + struct bnxt_qplib_sg_info *sginfo; + struct bnxt_qplib_srq *qplib_srq; + struct bnxt_re_ucontext *cntx; + struct ib_ucontext *context; + struct bnxt_re_srq_req ureq; + struct ib_umem *umem; + int rc, bytes = 0; + + context = pd->ibpd.uobject->context; + cntx = to_bnxt_re(context, struct bnxt_re_ucontext, ibucontext); + qplib_srq = &srq->qplib_srq; + sginfo = &qplib_srq->sginfo; + + if (udata->inlen < sizeof(ureq)) + dev_warn(rdev_to_dev(rdev), + "Update the library ulen %d klen %d\n", + (unsigned int)udata->inlen, + (unsigned int)sizeof(ureq)); + + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + return rc; + + bytes = (qplib_srq->max_wqe * qplib_srq->wqe_size); + bytes = PAGE_ALIGN(bytes); + umem = ib_umem_get_compat(rdev, context, udata, ureq.srqva, bytes, + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(umem)) { + dev_err(rdev_to_dev(rdev), "%s: ib_umem_get failed with %ld\n", + __func__, PTR_ERR(umem)); + return PTR_ERR(umem); + } + + srq->umem = umem; + sginfo->sghead = get_ib_umem_sgl(umem, &sginfo->nmap); + sginfo->npages = ib_umem_num_pages_compat(umem); + qplib_srq->srq_handle = ureq.srq_handle; + qplib_srq->dpi = &cntx->dpi; + qplib_srq->is_user = true; + + return 0; +} + +int bnxt_re_create_srq(struct ib_srq *srq_in, struct ib_srq_init_attr *srq_init_attr, + struct ib_udata *udata) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_re_ucontext *cntx = NULL; + struct ib_ucontext *context; + struct bnxt_re_dev *rdev; + struct bnxt_re_pd *pd; + int rc, entries; + struct ib_srq *ib_srq = srq_in; + struct ib_pd *ib_pd = ib_srq->pd; + struct bnxt_re_srq *srq = + container_of(ib_srq, struct bnxt_re_srq, ibsrq); + u32 max_srq_count; + + pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + rdev = pd->rdev; + dev_attr = rdev->dev_attr; + + if (rdev->mod_exit) { + dev_dbg(rdev_to_dev(rdev), "%s(): in mod_exit, just return!\n", __func__); + rc = -EIO; + goto exit; + } + + if (srq_init_attr->srq_type != IB_SRQT_BASIC) { + dev_err(rdev_to_dev(rdev), "SRQ type not supported\n"); + rc = -ENOTSUPP; + goto exit; + } + + if (udata) { + context = pd->ibpd.uobject->context; + cntx = to_bnxt_re(context, struct bnxt_re_ucontext, ibucontext); + } + + if (atomic_read(&rdev->stats.rsors.srq_count) >= dev_attr->max_srq) { + dev_err(rdev_to_dev(rdev), "Create SRQ failed - max exceeded(SRQs)\n"); + rc = -EINVAL; + goto exit; + } + + if (srq_init_attr->attr.max_wr >= dev_attr->max_srq_wqes) { + dev_err(rdev_to_dev(rdev), "Create SRQ failed - max exceeded(SRQ_WQs)\n"); + rc = -EINVAL; + goto exit; + } + + srq->rdev = rdev; + srq->qplib_srq.pd = &pd->qplib_pd; + srq->qplib_srq.dpi = &rdev->dpi_privileged; + + /* Allocate 1 more than what's provided so posting max doesn't + mean empty */ + entries = srq_init_attr->attr.max_wr + 1; + entries = bnxt_re_init_depth(entries, cntx); + if (entries > dev_attr->max_srq_wqes + 1) + entries = dev_attr->max_srq_wqes + 1; + + srq->qplib_srq.wqe_size = _max_rwqe_sz(6); /* 128 byte wqe size */ + srq->qplib_srq.max_wqe = entries; + srq->qplib_srq.max_sge = srq_init_attr->attr.max_sge; + srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit; + srq->srq_limit = srq_init_attr->attr.srq_limit; + srq->qplib_srq.eventq_hw_ring_id = rdev->nqr.nq[0].ring_id; + srq->qplib_srq.sginfo.pgsize = PAGE_SIZE; + srq->qplib_srq.sginfo.pgshft = PAGE_SHIFT; + + if (udata) { + rc = bnxt_re_init_user_srq(rdev, pd, srq, udata); + if (rc) + goto fail; + } + + rc = bnxt_qplib_create_srq(&rdev->qplib_res, &srq->qplib_srq); + if (rc) { + dev_err(rdev_to_dev(rdev), "Create HW SRQ failed!\n"); + goto fail; + } + + if (udata) { + struct bnxt_re_srq_resp resp; + + resp.srqid = srq->qplib_srq.id; + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) { + bnxt_qplib_destroy_srq(&rdev->qplib_res, &srq->qplib_srq); + goto fail; + } + } + atomic_inc(&rdev->stats.rsors.srq_count); + max_srq_count = atomic_read(&rdev->stats.rsors.srq_count); + if (max_srq_count > atomic_read(&rdev->stats.rsors.max_srq_count)) + atomic_set(&rdev->stats.rsors.max_srq_count, max_srq_count); + spin_lock_init(&srq->lock); + + return 0; +fail: + if (udata && srq->umem && !IS_ERR(srq->umem)) { + ib_umem_release(srq->umem); + srq->umem = NULL; + } +exit: + return rc; +} + +int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, + enum ib_srq_attr_mask srq_attr_mask, + struct ib_udata *udata) +{ + struct bnxt_re_srq *srq = to_bnxt_re(ib_srq, struct bnxt_re_srq, + ibsrq); + struct bnxt_re_dev *rdev = srq->rdev; + int rc; + + switch (srq_attr_mask) { + case IB_SRQ_MAX_WR: + /* SRQ resize is not supported */ + break; + case IB_SRQ_LIMIT: + /* Change the SRQ threshold */ + if (srq_attr->srq_limit > srq->qplib_srq.max_wqe) + return -EINVAL; + + srq->qplib_srq.threshold = srq_attr->srq_limit; + rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq); + if (rc) { + dev_err(rdev_to_dev(rdev), "Modify HW SRQ failed!\n"); + return rc; + } + /* On success, update the shadow */ + srq->srq_limit = srq_attr->srq_limit; + + if (udata) { + /* Build and send response back to udata */ + rc = bnxt_re_copy_to_udata(rdev, srq, 0, udata); + if (rc) + return rc; + } + break; + default: + dev_err(rdev_to_dev(rdev), + "Unsupported srq_attr_mask 0x%x\n", srq_attr_mask); + return -EINVAL; + } + return 0; +} + +int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr) +{ + struct bnxt_re_srq *srq = to_bnxt_re(ib_srq, struct bnxt_re_srq, + ibsrq); + struct bnxt_re_dev *rdev = srq->rdev; + int rc; + + rc = bnxt_qplib_query_srq(&rdev->qplib_res, &srq->qplib_srq); + if (rc) { + dev_err(rdev_to_dev(rdev), "Query HW SRQ (0x%x) failed! rc = %d\n", + srq->qplib_srq.id, rc); + return rc; + } + srq_attr->max_wr = srq->qplib_srq.max_wqe; + srq_attr->max_sge = srq->qplib_srq.max_sge; + srq_attr->srq_limit = srq->qplib_srq.threshold; + + return 0; +} + +int bnxt_re_post_srq_recv(struct ib_srq *ib_srq, const struct ib_recv_wr *wr, + const struct ib_recv_wr **bad_wr) +{ + struct bnxt_re_srq *srq = to_bnxt_re(ib_srq, struct bnxt_re_srq, + ibsrq); + struct bnxt_qplib_swqe wqe = {}; + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&srq->lock, flags); + while (wr) { + /* Transcribe each ib_recv_wr to qplib_swqe */ + wqe.num_sge = wr->num_sge; + wqe.sg_list = (struct bnxt_qplib_sge *)wr->sg_list; + wqe.wr_id = wr->wr_id; + wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV; + rc = bnxt_qplib_post_srq_recv(&srq->qplib_srq, &wqe); + if (rc) { + *bad_wr = wr; + break; + } + wr = wr->next; + } + spin_unlock_irqrestore(&srq->lock, flags); + + return rc; +} + +unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp) +{ + unsigned long flags; + + spin_lock_irqsave(&qp->scq->cq_lock, flags); + if (qp->rcq && qp->rcq != qp->scq) + spin_lock(&qp->rcq->cq_lock); + + return flags; +} + +void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, + unsigned long flags) +{ + if (qp->rcq && qp->rcq != qp->scq) + spin_unlock(&qp->rcq->cq_lock); + spin_unlock_irqrestore(&qp->scq->cq_lock, flags); +} + +/* Queue Pairs */ +static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp) +{ + struct bnxt_re_qp *gsi_sqp; + struct bnxt_re_ah *gsi_sah; + struct bnxt_re_dev *rdev; + unsigned long flags; + int rc = 0; + + rdev = qp->rdev; + gsi_sqp = rdev->gsi_ctx.gsi_sqp; + gsi_sah = rdev->gsi_ctx.gsi_sah; + + /* remove from active qp list */ + mutex_lock(&rdev->qp_lock); + list_del(&gsi_sqp->list); + mutex_unlock(&rdev->qp_lock); + + if (gsi_sah) { + dev_dbg(rdev_to_dev(rdev), "Destroy the shadow AH\n"); + rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &gsi_sah->qplib_ah, + true); + if (rc) + dev_err(rdev_to_dev(rdev), + "Destroy HW AH for shadow QP failed!\n"); + atomic_dec(&rdev->stats.rsors.ah_count); + } + + dev_dbg(rdev_to_dev(rdev), "Destroy the shadow QP\n"); + rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &gsi_sqp->qplib_qp); + if (rc) + dev_err(rdev_to_dev(rdev), "Destroy Shadow QP failed\n"); + + /* Clean the CQ for shadow QP completions */ + flags = bnxt_re_lock_cqs(gsi_sqp); + bnxt_qplib_clean_qp(&gsi_sqp->qplib_qp); + bnxt_re_unlock_cqs(gsi_sqp, flags); + + bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp); + bnxt_qplib_free_hdr_buf(&rdev->qplib_res, &gsi_sqp->qplib_qp); + kfree(rdev->gsi_ctx.sqp_tbl); + kfree(gsi_sah); + kfree(gsi_sqp); + rdev->gsi_ctx.gsi_sqp = NULL; + rdev->gsi_ctx.gsi_sah = NULL; + rdev->gsi_ctx.sqp_tbl = NULL; + atomic_dec(&rdev->stats.rsors.qp_count); + + return 0; +} + +static void bnxt_re_dump_debug_stats(struct bnxt_re_dev *rdev, u32 active_qps) +{ + u32 total_qp = 0; + u64 avg_time = 0; + int i; + + if (!rdev->rcfw.sp_perf_stats_enabled) + return; + + switch (active_qps) { + case 1: + /* Potential hint for Test Stop */ + for (i = 0; i < RCFW_MAX_STAT_INDEX; i++) { + if (rdev->rcfw.qp_destroy_stats[i]) { + total_qp++; + avg_time += rdev->rcfw.qp_destroy_stats[i]; + } + } + if (total_qp >= 0 || avg_time >= 0) + dev_dbg(rdev_to_dev(rdev), + "Perf Debug: %ps Total (%d) QP destroyed in (%ld) msec\n", + __builtin_return_address(0), total_qp, + (long)jiffies_to_msecs(avg_time)); + break; + case 2: + /* Potential hint for Test Start */ + dev_dbg(rdev_to_dev(rdev), + "Perf Debug: %ps active_qps = %d\n", + __builtin_return_address(0), active_qps); + break; + default: + /* Potential hint to know latency of QP destroy. + * Average time taken for 1K QP Destroy. + */ + if (active_qps > 1024 && !(active_qps % 1024)) + dev_dbg(rdev_to_dev(rdev), + "Perf Debug: %ps Active QP (%d) Watermark (%d)\n", + __builtin_return_address(0), active_qps, + atomic_read(&rdev->stats.rsors.max_qp_count)); + break; + } +} + +int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata) +{ + struct bnxt_re_qp *qp = to_bnxt_re(ib_qp, struct bnxt_re_qp, ib_qp); + struct bnxt_re_dev *rdev = qp->rdev; + unsigned long flags; + u32 active_qps; + int rc; + + mutex_lock(&rdev->qp_lock); + list_del(&qp->list); + active_qps = atomic_dec_return(&rdev->stats.rsors.qp_count); + if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_RC) + atomic_dec(&rdev->stats.rsors.rc_qp_count); + else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD) + atomic_dec(&rdev->stats.rsors.ud_qp_count); + mutex_unlock(&rdev->qp_lock); + + rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp); + if (rc) + dev_err_ratelimited(rdev_to_dev(rdev), + "%s id = %d failed rc = %d\n", + __func__, qp->qplib_qp.id, rc); + + if (!ib_qp->uobject) { + flags = bnxt_re_lock_cqs(qp); + bnxt_qplib_clean_qp(&qp->qplib_qp); + bnxt_re_unlock_cqs(qp, flags); + } + + bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp); + if (ib_qp->qp_type == IB_QPT_GSI && + rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_UD) { + if (rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ALL && + rdev->gsi_ctx.gsi_sqp) { + bnxt_re_destroy_gsi_sqp(qp); + } + bnxt_qplib_free_hdr_buf(&rdev->qplib_res, &qp->qplib_qp); + } + + if (qp->rumem && !IS_ERR(qp->rumem)) + ib_umem_release(qp->rumem); + if (qp->sumem && !IS_ERR(qp->sumem)) + ib_umem_release(qp->sumem); + kfree(qp); + + bnxt_re_dump_debug_stats(rdev, active_qps); + + return 0; +} + +static u8 __from_ib_qp_type(enum ib_qp_type type) +{ + switch (type) { + case IB_QPT_GSI: + return CMDQ_CREATE_QP1_TYPE_GSI; + case IB_QPT_RC: + return CMDQ_CREATE_QP_TYPE_RC; + case IB_QPT_UD: + return CMDQ_CREATE_QP_TYPE_UD; + case IB_QPT_RAW_ETHERTYPE: + return CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE; + default: + return IB_QPT_MAX; + } +} + +static u16 _get_swqe_sz(int nsge) +{ + return sizeof(struct sq_send_hdr) + nsge * sizeof(struct sq_sge); +} + +static int bnxt_re_get_swqe_size(int ilsize, int nsge) +{ + u16 wqe_size, calc_ils; + + wqe_size = _get_swqe_sz(nsge); + if (ilsize) { + calc_ils = (sizeof(struct sq_send_hdr) + ilsize); + wqe_size = max_t(int, calc_ils, wqe_size); + wqe_size = ALIGN(wqe_size, 32); + } + return wqe_size; +} + +static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_q *sq; + int align, ilsize; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + sq = &qplqp->sq; + dev_attr = rdev->dev_attr; + + align = sizeof(struct sq_send_hdr); + ilsize = ALIGN(init_attr->cap.max_inline_data, align); + + sq->wqe_size = bnxt_re_get_swqe_size(ilsize, sq->max_sge); + if (sq->wqe_size > _get_swqe_sz(dev_attr->max_qp_sges)) + return -EINVAL; + /* For Cu/Wh and gen p5 backward compatibility mode + * wqe size is fixed to 128 bytes + */ + if (sq->wqe_size < _get_swqe_sz(dev_attr->max_qp_sges) && + qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + sq->wqe_size = _get_swqe_sz(dev_attr->max_qp_sges); + + if (init_attr->cap.max_inline_data) { + qplqp->max_inline_data = sq->wqe_size - + sizeof(struct sq_send_hdr); + init_attr->cap.max_inline_data = qplqp->max_inline_data; + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + sq->max_sge = qplqp->max_inline_data / + sizeof(struct sq_sge); + } + + return 0; +} + +static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, + struct bnxt_re_pd *pd, struct bnxt_re_qp *qp, + struct ib_udata *udata) +{ + struct bnxt_qplib_sg_info *sginfo; + struct bnxt_qplib_qp *qplib_qp; + struct bnxt_re_ucontext *cntx; + struct ib_ucontext *context; + struct bnxt_re_qp_req ureq; + struct ib_umem *umem; + int rc, bytes = 0; + int psn_nume; + int psn_sz; + + qplib_qp = &qp->qplib_qp; + context = pd->ibpd.uobject->context; + cntx = to_bnxt_re(context, struct bnxt_re_ucontext, ibucontext); + sginfo = &qplib_qp->sq.sginfo; + + if (udata->inlen < sizeof(ureq)) + dev_warn(rdev_to_dev(rdev), + "Update the library ulen %d klen %d\n", + (unsigned int)udata->inlen, + (unsigned int)sizeof(ureq)); + + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + return rc; + + bytes = (qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size); + /* Consider mapping PSN search memory only for RC QPs. */ + if (qplib_qp->type == CMDQ_CREATE_QP_TYPE_RC) { + psn_sz = _is_chip_gen_p5_p7(rdev->chip_ctx) ? + sizeof(struct sq_psn_search_ext) : + sizeof(struct sq_psn_search); + if (rdev->dev_attr && BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) + psn_sz = sizeof(struct sq_msn_search); + psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + qplib_qp->sq.max_wqe : + ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) / + sizeof(struct bnxt_qplib_sge)); + if (BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) + psn_nume = roundup_pow_of_two(psn_nume); + + bytes += (psn_nume * psn_sz); + } + bytes = PAGE_ALIGN(bytes); + umem = ib_umem_get_compat(rdev, context, udata, ureq.qpsva, bytes, + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(umem)) { + dev_err(rdev_to_dev(rdev), "%s: ib_umem_get failed with %ld\n", + __func__, PTR_ERR(umem)); + return PTR_ERR(umem); + } + + qp->sumem = umem; + /* pgsize and pgshft were initialize already. */ + sginfo->sghead = get_ib_umem_sgl(umem, &sginfo->nmap); + sginfo->npages = ib_umem_num_pages_compat(umem); + qplib_qp->qp_handle = ureq.qp_handle; + + if (!qp->qplib_qp.srq) { + sginfo = &qplib_qp->rq.sginfo; + bytes = (qplib_qp->rq.max_wqe * qplib_qp->rq.wqe_size); + bytes = PAGE_ALIGN(bytes); + umem = ib_umem_get_compat(rdev, + context, udata, ureq.qprva, bytes, + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(umem)) { + dev_err(rdev_to_dev(rdev), + "%s: ib_umem_get failed ret =%ld\n", + __func__, PTR_ERR(umem)); + goto rqfail; + } + qp->rumem = umem; + /* pgsize and pgshft were initialize already. */ + sginfo->sghead = get_ib_umem_sgl(umem, &sginfo->nmap); + sginfo->npages = ib_umem_num_pages_compat(umem); + } + + qplib_qp->dpi = &cntx->dpi; + qplib_qp->is_user = true; + + return 0; +rqfail: + ib_umem_release(qp->sumem); + qp->sumem = NULL; + qplib_qp->sq.sginfo.sghead = NULL; + qplib_qp->sq.sginfo.nmap = 0; + + return PTR_ERR(umem); +} + +static struct bnxt_re_ah *bnxt_re_create_shadow_qp_ah(struct bnxt_re_pd *pd, + struct bnxt_qplib_res *qp1_res, + struct bnxt_qplib_qp *qp1_qp) +{ + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_ah *ah; + union ib_gid sgid; + int rc; + + ah = kzalloc(sizeof(*ah), GFP_KERNEL); + if (!ah) { + dev_err(rdev_to_dev(rdev), "Allocate Address Handle failed!\n"); + return NULL; + } + memset(ah, 0, sizeof(*ah)); + ah->rdev = rdev; + ah->qplib_ah.pd = &pd->qplib_pd; + + rc = bnxt_re_query_gid(&rdev->ibdev, 1, 0, &sgid); + if (rc) + goto fail; + + /* supply the dgid data same as sgid */ + memcpy(ah->qplib_ah.dgid.data, &sgid.raw, + sizeof(union ib_gid)); + ah->qplib_ah.sgid_index = 0; + + ah->qplib_ah.traffic_class = 0; + ah->qplib_ah.flow_label = 0; + ah->qplib_ah.hop_limit = 1; + ah->qplib_ah.sl = 0; + /* Have DMAC same as SMAC */ + ether_addr_copy(ah->qplib_ah.dmac, rdev->dev_addr); + dev_dbg(rdev_to_dev(rdev), "ah->qplib_ah.dmac = %x:%x:%x:%x:%x:%x\n", + ah->qplib_ah.dmac[0], ah->qplib_ah.dmac[1], ah->qplib_ah.dmac[2], + ah->qplib_ah.dmac[3], ah->qplib_ah.dmac[4], ah->qplib_ah.dmac[5]); + + rc = bnxt_qplib_create_ah(&rdev->qplib_res, &ah->qplib_ah, true); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Allocate HW AH for Shadow QP failed!\n"); + goto fail; + } + dev_dbg(rdev_to_dev(rdev), "AH ID = %d\n", ah->qplib_ah.id); + atomic_inc(&rdev->stats.rsors.ah_count); + + return ah; +fail: + kfree(ah); + return NULL; +} + +void bnxt_re_update_shadow_ah(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_qp *gsi_qp; + struct bnxt_re_ah *sah; + struct bnxt_re_pd *pd; + struct ib_pd *ib_pd; + int rc; + + if (!rdev) + return; + + sah = rdev->gsi_ctx.gsi_sah; + + dev_dbg(rdev_to_dev(rdev), "Updating the AH\n"); + if (sah) { + /* Check if the AH created with current mac address */ + if (!compare_ether_header(sah->qplib_ah.dmac, rdev->dev_addr)) { + dev_dbg(rdev_to_dev(rdev), + "Not modifying shadow AH during AH update\n"); + return; + } + + gsi_qp = rdev->gsi_ctx.gsi_qp; + ib_pd = gsi_qp->ib_qp.pd; + pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, + &sah->qplib_ah, false); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to destroy shadow AH during AH update\n"); + return; + } + atomic_dec(&rdev->stats.rsors.ah_count); + kfree(sah); + rdev->gsi_ctx.gsi_sah = NULL; + + sah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res, + &gsi_qp->qplib_qp); + if (!sah) { + dev_err(rdev_to_dev(rdev), + "Failed to update AH for ShadowQP\n"); + return; + } + rdev->gsi_ctx.gsi_sah = sah; + atomic_inc(&rdev->stats.rsors.ah_count); + } +} + +static struct bnxt_re_qp *bnxt_re_create_shadow_qp(struct bnxt_re_pd *pd, + struct bnxt_qplib_res *qp1_res, + struct bnxt_qplib_qp *qp1_qp) +{ + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_qp *qp; + int rc; + + qp = kzalloc(sizeof(*qp), GFP_KERNEL); + if (!qp) { + dev_err(rdev_to_dev(rdev), "Allocate internal UD QP failed!\n"); + return NULL; + } + memset(qp, 0, sizeof(*qp)); + qp->rdev = rdev; + + /* Initialize the shadow QP structure from the QP1 values */ + ether_addr_copy(qp->qplib_qp.smac, rdev->dev_addr); + qp->qplib_qp.pd = &pd->qplib_pd; + qp->qplib_qp.qp_handle = (u64)&qp->qplib_qp; + qp->qplib_qp.type = IB_QPT_UD; + + qp->qplib_qp.max_inline_data = 0; + qp->qplib_qp.sig_type = true; + + /* Shadow QP SQ depth should be same as QP1 RQ depth */ + qp->qplib_qp.sq.wqe_size = bnxt_re_get_swqe_size(0, 6); + qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.sq.max_sge = 2; + /* Q full delta can be 1 since it is internal QP */ + qp->qplib_qp.sq.q_full_delta = 1; + qp->qplib_qp.sq.sginfo.pgsize = PAGE_SIZE; + qp->qplib_qp.sq.sginfo.pgshft = PAGE_SHIFT; + + qp->qplib_qp.scq = qp1_qp->scq; + qp->qplib_qp.rcq = qp1_qp->rcq; + + qp->qplib_qp.rq.wqe_size = _max_rwqe_sz(6); /* 128 Byte wqe size */ + qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge; + qp->qplib_qp.rq.sginfo.pgsize = PAGE_SIZE; + qp->qplib_qp.rq.sginfo.pgshft = PAGE_SHIFT; + /* Q full delta can be 1 since it is internal QP */ + qp->qplib_qp.rq.q_full_delta = 1; + qp->qplib_qp.mtu = qp1_qp->mtu; + qp->qplib_qp.dpi = &rdev->dpi_privileged; + + rc = bnxt_qplib_alloc_hdr_buf(qp1_res, &qp->qplib_qp, 0, + BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6); + if (rc) + goto fail; + + rc = bnxt_qplib_create_qp(qp1_res, &qp->qplib_qp); + if (rc) { + dev_err(rdev_to_dev(rdev), "create HW QP failed!\n"); + goto qp_fail; + } + + dev_dbg(rdev_to_dev(rdev), "Created shadow QP with ID = %d\n", + qp->qplib_qp.id); + spin_lock_init(&qp->sq_lock); + INIT_LIST_HEAD(&qp->list); + mutex_lock(&rdev->qp_lock); + list_add_tail(&qp->list, &rdev->qp_list); + atomic_inc(&rdev->stats.rsors.qp_count); + mutex_unlock(&rdev->qp_lock); + return qp; +qp_fail: + bnxt_qplib_free_hdr_buf(qp1_res, &qp->qplib_qp); +fail: + kfree(qp); + return NULL; +} + +static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr, void *cntx) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_q *rq; + int entries; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + rq = &qplqp->rq; + dev_attr = rdev->dev_attr; + + if (init_attr->srq) { + struct bnxt_re_srq *srq; + + srq = to_bnxt_re(init_attr->srq, struct bnxt_re_srq, ibsrq); + if (!srq) { + dev_err(rdev_to_dev(rdev), "SRQ not found\n"); + return -EINVAL; + } + qplqp->srq = &srq->qplib_srq; + rq->max_wqe = 0; + } else { + rq->max_sge = init_attr->cap.max_recv_sge; + if (rq->max_sge > dev_attr->max_qp_sges) + rq->max_sge = dev_attr->max_qp_sges; + init_attr->cap.max_recv_sge = rq->max_sge; + rq->wqe_size = bnxt_re_get_rwqe_size(qplqp, rq->max_sge, + dev_attr->max_qp_sges); + + /* Allocate 1 more than what's provided so posting max doesn't + mean empty */ + entries = init_attr->cap.max_recv_wr + 1; + entries = bnxt_re_init_depth(entries, cntx); + rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1); + rq->q_full_delta = 0; + rq->sginfo.pgsize = PAGE_SIZE; + rq->sginfo.pgshft = PAGE_SHIFT; + } + + return 0; +} + +static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + dev_attr = rdev->dev_attr; + + if (rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_UD) + qplqp->rq.max_sge = dev_attr->max_qp_sges; +} + +static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr, + void *cntx) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_q *sq; + int diff = 0; + int entries; + int rc; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + sq = &qplqp->sq; + dev_attr = rdev->dev_attr; + + sq->max_sge = init_attr->cap.max_send_sge; + if (sq->max_sge > dev_attr->max_qp_sges) { + sq->max_sge = dev_attr->max_qp_sges; + init_attr->cap.max_send_sge = sq->max_sge; + } + rc = bnxt_re_setup_swqe_size(qp, init_attr); + if (rc) + return rc; + /* + * Change the SQ depth if user has requested minimum using + * configfs. Only supported for kernel consumers. Setting + * min_tx_depth to 4096 to handle iser SQ full condition + * in most of the newer OS distros + */ + entries = init_attr->cap.max_send_wr; + if (!cntx && rdev->min_tx_depth && init_attr->qp_type != IB_QPT_GSI) { + /* + * If users specify any value greater than 1 use min_tx_depth + * provided by user for comparison. Else, compare it with the + * BNXT_RE_MIN_KERNEL_QP_TX_DEPTH and adjust it accordingly. + */ + if (rdev->min_tx_depth > 1 && entries < rdev->min_tx_depth) + entries = rdev->min_tx_depth; + else if (entries < BNXT_RE_MIN_KERNEL_QP_TX_DEPTH) + entries = BNXT_RE_MIN_KERNEL_QP_TX_DEPTH; + } + diff = bnxt_re_get_diff(cntx, rdev->chip_ctx); + entries = bnxt_re_init_depth(entries + diff + 1, cntx); + sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1); + sq->q_full_delta = diff + 1; + /* + * Reserving one slot for Phantom WQE. Application can + * post one extra entry in this case. But allowing this to avoid + * unexpected Queue full condition + */ + sq->q_full_delta -= 1; /* becomes 0 for gen-p5 */ + sq->sginfo.pgsize = PAGE_SIZE; + sq->sginfo.pgshft = PAGE_SHIFT; + return 0; +} + +static void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp, + struct ib_qp_init_attr *init_attr, + void *cntx) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + int entries; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + dev_attr = rdev->dev_attr; + + if (rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_UD) { + entries = init_attr->cap.max_send_wr + 1; + entries = bnxt_re_init_depth(entries, cntx); + qplqp->sq.max_wqe = min_t(u32, entries, + dev_attr->max_qp_wqes + 1); + qplqp->sq.q_full_delta = qplqp->sq.max_wqe - + init_attr->cap.max_send_wr; + qplqp->sq.max_sge++; /* Need one extra sge to put UD header */ + if (qplqp->sq.max_sge > dev_attr->max_qp_sges) + qplqp->sq.max_sge = dev_attr->max_qp_sges; + } +} + +static int bnxt_re_init_qp_type(struct bnxt_re_dev *rdev, + struct ib_qp_init_attr *init_attr) +{ + struct bnxt_qplib_chip_ctx *chip_ctx; + struct bnxt_re_gsi_context *gsi_ctx; + int qptype; + + chip_ctx = rdev->chip_ctx; + gsi_ctx = &rdev->gsi_ctx; + + qptype = __from_ib_qp_type(init_attr->qp_type); + if (qptype == IB_QPT_MAX) { + dev_err(rdev_to_dev(rdev), "QP type 0x%x not supported\n", + qptype); + qptype = -EINVAL; + goto out; + } + + if (_is_chip_gen_p5_p7(chip_ctx) && init_attr->qp_type == IB_QPT_GSI) { + /* For Thor always force UD mode. */ + qptype = CMDQ_CREATE_QP_TYPE_GSI; + gsi_ctx->gsi_qp_mode = BNXT_RE_GSI_MODE_UD; + } +out: + return qptype; +} + +static int bnxt_re_init_qp_wqe_mode(struct bnxt_re_dev *rdev) +{ + return rdev->chip_ctx->modes.wqe_mode; +} + +static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_re_ucontext *cntx = NULL; + struct ib_ucontext *context; + struct bnxt_qplib_qp *qplqp; + struct bnxt_re_dev *rdev; + struct bnxt_re_cq *cq; + int rc = 0, qptype; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + dev_attr = rdev->dev_attr; + + if (udata) { + context = pd->ibpd.uobject->context; + cntx = to_bnxt_re(context, struct bnxt_re_ucontext, ibucontext); + } + + /* Setup misc params */ + qplqp->is_user = false; + qplqp->pd = &pd->qplib_pd; + qplqp->qp_handle = (u64)qplqp; + qplqp->sig_type = ((init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? + true : false); + qptype = bnxt_re_init_qp_type(rdev, init_attr); + if (qptype < 0) { + rc = qptype; + goto out; + } + qplqp->type = (u8)qptype; + qplqp->wqe_mode = bnxt_re_init_qp_wqe_mode(rdev); + ether_addr_copy(qplqp->smac, rdev->dev_addr); + + if (init_attr->qp_type == IB_QPT_RC) { + qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom; + qplqp->max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom; + } + qplqp->mtu = ib_mtu_enum_to_int(iboe_get_mtu(if_getmtu(rdev->netdev))); + qplqp->dpi = &rdev->dpi_privileged; /* Doorbell page */ + if (init_attr->create_flags) { + dev_dbg(rdev_to_dev(rdev), + "QP create flags 0x%x not supported\n", + init_attr->create_flags); + return -EOPNOTSUPP; + } + + /* Setup CQs */ + if (init_attr->send_cq) { + cq = to_bnxt_re(init_attr->send_cq, struct bnxt_re_cq, ibcq); + if (!cq) { + dev_err(rdev_to_dev(rdev), "Send CQ not found\n"); + rc = -EINVAL; + goto out; + } + qplqp->scq = &cq->qplib_cq; + qp->scq = cq; + } + + if (init_attr->recv_cq) { + cq = to_bnxt_re(init_attr->recv_cq, struct bnxt_re_cq, ibcq); + if (!cq) { + dev_err(rdev_to_dev(rdev), "Receive CQ not found\n"); + rc = -EINVAL; + goto out; + } + qplqp->rcq = &cq->qplib_cq; + qp->rcq = cq; + } + + /* Setup RQ/SRQ */ + rc = bnxt_re_init_rq_attr(qp, init_attr, cntx); + if (rc) + goto out; + if (init_attr->qp_type == IB_QPT_GSI) + bnxt_re_adjust_gsi_rq_attr(qp); + + /* Setup SQ */ + rc = bnxt_re_init_sq_attr(qp, init_attr, cntx); + if (rc) + goto out; + if (init_attr->qp_type == IB_QPT_GSI) + bnxt_re_adjust_gsi_sq_attr(qp, init_attr, cntx); + + if (udata) /* This will update DPI and qp_handle */ + rc = bnxt_re_init_user_qp(rdev, pd, qp, udata); +out: + return rc; +} + +static int bnxt_re_create_shadow_gsi(struct bnxt_re_qp *qp, + struct bnxt_re_pd *pd) +{ + struct bnxt_re_sqp_entries *sqp_tbl = NULL; + struct bnxt_re_dev *rdev; + struct bnxt_re_qp *sqp; + struct bnxt_re_ah *sah; + int rc = 0; + + rdev = qp->rdev; + /* Create a shadow QP to handle the QP1 traffic */ + sqp_tbl = kzalloc(sizeof(*sqp_tbl) * BNXT_RE_MAX_GSI_SQP_ENTRIES, + GFP_KERNEL); + if (!sqp_tbl) + return -ENOMEM; + rdev->gsi_ctx.sqp_tbl = sqp_tbl; + + sqp = bnxt_re_create_shadow_qp(pd, &rdev->qplib_res, &qp->qplib_qp); + if (!sqp) { + rc = -ENODEV; + dev_err(rdev_to_dev(rdev), + "Failed to create Shadow QP for QP1\n"); + goto out; + } + rdev->gsi_ctx.gsi_sqp = sqp; + + sqp->rcq = qp->rcq; + sqp->scq = qp->scq; + sah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res, + &qp->qplib_qp); + if (!sah) { + bnxt_qplib_destroy_qp(&rdev->qplib_res, + &sqp->qplib_qp); + rc = -ENODEV; + dev_err(rdev_to_dev(rdev), + "Failed to create AH entry for ShadowQP\n"); + goto out; + } + rdev->gsi_ctx.gsi_sah = sah; + + return 0; +out: + kfree(sqp_tbl); + return rc; +} + +static int __get_rq_hdr_buf_size(u8 gsi_mode) +{ + return (gsi_mode == BNXT_RE_GSI_MODE_ALL) ? + BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2 : + BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE; +} + +static int __get_sq_hdr_buf_size(u8 gsi_mode) +{ + return (gsi_mode != BNXT_RE_GSI_MODE_ROCE_V1) ? + BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2 : + BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE; +} + +static int bnxt_re_create_gsi_qp(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd) +{ + struct bnxt_qplib_qp *qplqp; + struct bnxt_qplib_res *res; + struct bnxt_re_dev *rdev; + u32 sstep, rstep; + u8 gsi_mode; + int rc = 0; + + rdev = qp->rdev; + qplqp = &qp->qplib_qp; + res = &rdev->qplib_res; + gsi_mode = rdev->gsi_ctx.gsi_qp_mode; + + rstep = __get_rq_hdr_buf_size(gsi_mode); + sstep = __get_sq_hdr_buf_size(gsi_mode); + rc = bnxt_qplib_alloc_hdr_buf(res, qplqp, sstep, rstep); + if (rc) + goto out; + + rc = bnxt_qplib_create_qp1(res, qplqp); + if (rc) { + dev_err(rdev_to_dev(rdev), "create HW QP1 failed!\n"); + goto out; + } + + if (gsi_mode == BNXT_RE_GSI_MODE_ALL) + rc = bnxt_re_create_shadow_gsi(qp, pd); +out: + return rc; +} + +static bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev, + struct ib_qp_init_attr *init_attr, + struct bnxt_qplib_dev_attr *dev_attr) +{ + bool rc = true; + int ilsize; + + ilsize = ALIGN(init_attr->cap.max_inline_data, sizeof(struct sq_sge)); + if ((init_attr->cap.max_send_wr > dev_attr->max_qp_wqes) || + (init_attr->cap.max_recv_wr > dev_attr->max_qp_wqes) || + (init_attr->cap.max_send_sge > dev_attr->max_qp_sges) || + (init_attr->cap.max_recv_sge > dev_attr->max_qp_sges) || + (ilsize > dev_attr->max_inline_data)) { + dev_err(rdev_to_dev(rdev), "Create QP failed - max exceeded! " + "0x%x/0x%x 0x%x/0x%x 0x%x/0x%x " + "0x%x/0x%x 0x%x/0x%x\n", + init_attr->cap.max_send_wr, dev_attr->max_qp_wqes, + init_attr->cap.max_recv_wr, dev_attr->max_qp_wqes, + init_attr->cap.max_send_sge, dev_attr->max_qp_sges, + init_attr->cap.max_recv_sge, dev_attr->max_qp_sges, + init_attr->cap.max_inline_data, + dev_attr->max_inline_data); + rc = false; + } + return rc; +} + +static inline struct +bnxt_re_qp *__get_qp_from_qp_in(struct ib_pd *qp_in, + struct bnxt_re_dev *rdev) +{ + struct bnxt_re_qp *qp; + + qp = kzalloc(sizeof(*qp), GFP_KERNEL); + if (!qp) + dev_err(rdev_to_dev(rdev), "Allocate QP failed!\n"); + return qp; +} + +struct ib_qp *bnxt_re_create_qp(struct ib_pd *qp_in, + struct ib_qp_init_attr *qp_init_attr, + struct ib_udata *udata) +{ + struct bnxt_re_pd *pd; + struct ib_pd *ib_pd = qp_in; + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_re_dev *rdev; + u32 active_qps, tmp_qps; + struct bnxt_re_qp *qp; + int rc; + + pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + rdev = pd->rdev; + dev_attr = rdev->dev_attr; + if (rdev->mod_exit) { + rc = -EIO; + dev_dbg(rdev_to_dev(rdev), "%s(): in mod_exit, just return!\n", __func__); + goto exit; + } + + if (atomic_read(&rdev->stats.rsors.qp_count) >= dev_attr->max_qp) { + dev_err(rdev_to_dev(rdev), "Create QP failed - max exceeded(QPs Alloc'd %u of max %u)\n", + atomic_read(&rdev->stats.rsors.qp_count), dev_attr->max_qp); + rc = -EINVAL; + goto exit; + } + + rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr); + if (!rc) { + rc = -EINVAL; + goto exit; + } + qp = __get_qp_from_qp_in(qp_in, rdev); + if (!qp) { + rc = -ENOMEM; + goto exit; + } + qp->rdev = rdev; + + rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata); + if (rc) + goto fail; + + if (qp_init_attr->qp_type == IB_QPT_GSI && + !_is_chip_gen_p5_p7(rdev->chip_ctx)) { + rc = bnxt_re_create_gsi_qp(qp, pd); + if (rc == -ENODEV) + goto qp_destroy; + if (rc) + goto fail; + } else { + rc = bnxt_qplib_create_qp(&rdev->qplib_res, &qp->qplib_qp); + if (rc) { + dev_err(rdev_to_dev(rdev), "create HW QP failed!\n"); + goto free_umem; + } + + if (udata) { + struct bnxt_re_qp_resp resp; + + resp.qpid = qp->qplib_qp.id; + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) + goto qp_destroy; + } + } + + qp->ib_qp.qp_num = qp->qplib_qp.id; + if (qp_init_attr->qp_type == IB_QPT_GSI) + rdev->gsi_ctx.gsi_qp = qp; + spin_lock_init(&qp->sq_lock); + spin_lock_init(&qp->rq_lock); + INIT_LIST_HEAD(&qp->list); + mutex_lock(&rdev->qp_lock); + list_add_tail(&qp->list, &rdev->qp_list); + mutex_unlock(&rdev->qp_lock); + atomic_inc(&rdev->stats.rsors.qp_count); + active_qps = atomic_read(&rdev->stats.rsors.qp_count); + if (active_qps > atomic_read(&rdev->stats.rsors.max_qp_count)) + atomic_set(&rdev->stats.rsors.max_qp_count, active_qps); + + bnxt_re_dump_debug_stats(rdev, active_qps); + + /* Get the counters for RC QPs and UD QPs */ + if (qp_init_attr->qp_type == IB_QPT_RC) { + tmp_qps = atomic_inc_return(&rdev->stats.rsors.rc_qp_count); + if (tmp_qps > atomic_read(&rdev->stats.rsors.max_rc_qp_count)) + atomic_set(&rdev->stats.rsors.max_rc_qp_count, tmp_qps); + } else if (qp_init_attr->qp_type == IB_QPT_UD) { + tmp_qps = atomic_inc_return(&rdev->stats.rsors.ud_qp_count); + if (tmp_qps > atomic_read(&rdev->stats.rsors.max_ud_qp_count)) + atomic_set(&rdev->stats.rsors.max_ud_qp_count, tmp_qps); + } + + return &qp->ib_qp; + +qp_destroy: + bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp); +free_umem: + if (udata) { + if (qp->rumem && !IS_ERR(qp->rumem)) + ib_umem_release(qp->rumem); + if (qp->sumem && !IS_ERR(qp->sumem)) + ib_umem_release(qp->sumem); + } +fail: + kfree(qp); +exit: + return ERR_PTR(rc); +} + +static int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp1_qp, + int qp_attr_mask) +{ + struct bnxt_re_qp *qp = rdev->gsi_ctx.gsi_sqp; + int rc = 0; + + if (qp_attr_mask & IB_QP_STATE) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE; + qp->qplib_qp.state = qp1_qp->qplib_qp.state; + } + if (qp_attr_mask & IB_QP_PKEY_INDEX) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY; + qp->qplib_qp.pkey_index = qp1_qp->qplib_qp.pkey_index; + } + + if (qp_attr_mask & IB_QP_QKEY) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY; + /* Using a Random QKEY */ + qp->qplib_qp.qkey = BNXT_RE_QP_RANDOM_QKEY; + } + if (qp_attr_mask & IB_QP_SQ_PSN) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN; + qp->qplib_qp.sq.psn = qp1_qp->qplib_qp.sq.psn; + } + + rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp); + if (rc) + dev_err(rdev_to_dev(rdev), "Modify Shadow QP for QP1 failed\n"); + return rc; +} + +static u32 ipv4_from_gid(u8 *gid) +{ + return (gid[15] << 24 | gid[14] << 16 | gid[13] << 8 | gid[12]); +} + +static u16 get_source_port(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp) +{ + u8 ip_off, data[48], smac[ETH_ALEN]; + u16 crc = 0, buf_len = 0, i; + u8 addr_len; + u32 qpn; + + if (qp->qplib_qp.nw_type == CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV6) { + addr_len = 6; + ip_off = 10; + } else { + addr_len = 4; + ip_off = 12; + } + + memcpy(smac, qp->qplib_qp.smac, ETH_ALEN); + + memset(data, 0, 48); + memcpy(data, qp->qplib_qp.ah.dmac, ETH_ALEN); + buf_len += ETH_ALEN; + + memcpy(data + buf_len, smac, ETH_ALEN); + buf_len += ETH_ALEN; + + memcpy(data + buf_len, qp->qplib_qp.ah.dgid.data + ip_off, addr_len); + buf_len += addr_len; + + memcpy(data + buf_len, qp->qp_info_entry.sgid.raw + ip_off, addr_len); + buf_len += addr_len; + + qpn = htonl(qp->qplib_qp.dest_qpn); + memcpy(data + buf_len, (u8 *)&qpn + 1, 3); + buf_len += 3; + + for (i = 0; i < buf_len; i++) + crc = crc16(crc, (data + i), 1); + + return crc; +} + +static void bnxt_re_update_qp_info(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp) +{ + u16 type; + + type = __from_hw_to_ib_qp_type(qp->qplib_qp.type); + + /* User-space can extract ip address with sgid_index. */ + if (ipv6_addr_v4mapped((struct in6_addr *)&qp->qplib_qp.ah.dgid)) { + qp->qp_info_entry.s_ip.ipv4_addr = ipv4_from_gid(qp->qp_info_entry.sgid.raw); + qp->qp_info_entry.d_ip.ipv4_addr = ipv4_from_gid(qp->qplib_qp.ah.dgid.data); + } else { + memcpy(&qp->qp_info_entry.s_ip.ipv6_addr, qp->qp_info_entry.sgid.raw, + sizeof(qp->qp_info_entry.s_ip.ipv6_addr)); + memcpy(&qp->qp_info_entry.d_ip.ipv6_addr, qp->qplib_qp.ah.dgid.data, + sizeof(qp->qp_info_entry.d_ip.ipv6_addr)); + } + + if (type == IB_QPT_RC && + (qp->qplib_qp.nw_type == CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV4 || + qp->qplib_qp.nw_type == CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV6)) { + qp->qp_info_entry.s_port = get_source_port(rdev, qp); + } + qp->qp_info_entry.d_port = BNXT_RE_QP_DEST_PORT; +} + +static void bnxt_qplib_manage_flush_qp(struct bnxt_re_qp *qp) +{ + struct bnxt_qplib_q *rq, *sq; + unsigned long flags; + + if (qp->sumem) + return; + + if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { + rq = &qp->qplib_qp.rq; + sq = &qp->qplib_qp.sq; + + dev_dbg(rdev_to_dev(qp->rdev), + "Move QP = %p to flush list\n", qp); + flags = bnxt_re_lock_cqs(qp); + bnxt_qplib_add_flush_qp(&qp->qplib_qp); + bnxt_re_unlock_cqs(qp, flags); + + if (sq->hwq.prod != sq->hwq.cons) + bnxt_re_handle_cqn(&qp->scq->qplib_cq); + + if (qp->rcq && (qp->rcq != qp->scq) && + (rq->hwq.prod != rq->hwq.cons)) + bnxt_re_handle_cqn(&qp->rcq->qplib_cq); + } + + if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_RESET) { + dev_dbg(rdev_to_dev(qp->rdev), + "Move QP = %p out of flush list\n", qp); + flags = bnxt_re_lock_cqs(qp); + bnxt_qplib_clean_qp(&qp->qplib_qp); + bnxt_re_unlock_cqs(qp, flags); + } +} + +bool ib_modify_qp_is_ok_compat(enum ib_qp_state cur_state, + enum ib_qp_state next_state, + enum ib_qp_type type, + enum ib_qp_attr_mask mask) +{ + return (ib_modify_qp_is_ok(cur_state, next_state, + type, mask)); +} + +int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, + int qp_attr_mask, struct ib_udata *udata) +{ + enum ib_qp_state curr_qp_state, new_qp_state; + struct bnxt_re_modify_qp_ex_resp resp = {}; + struct bnxt_re_modify_qp_ex_req ureq = {}; + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_qplib_ppp *ppp = NULL; + struct bnxt_re_dev *rdev; + struct bnxt_re_qp *qp; + struct ib_gid_attr *sgid_attr; + struct ib_gid_attr gid_attr; + union ib_gid sgid, *gid_ptr = NULL; + u8 nw_type; + int rc, entries, status; + bool is_copy_to_udata = false; + bool is_qpmtu_high = false; + + qp = to_bnxt_re(ib_qp, struct bnxt_re_qp, ib_qp); + rdev = qp->rdev; + dev_attr = rdev->dev_attr; + + qp->qplib_qp.modify_flags = 0; + ppp = &qp->qplib_qp.ppp; + if (qp_attr_mask & IB_QP_STATE) { + curr_qp_state = __to_ib_qp_state(qp->qplib_qp.cur_qp_state); + new_qp_state = qp_attr->qp_state; + if (!ib_modify_qp_is_ok_compat(curr_qp_state, new_qp_state, + ib_qp->qp_type, qp_attr_mask)) { + dev_err(rdev_to_dev(rdev),"invalid attribute mask=0x%x" + " specified for qpn=0x%x of type=0x%x" + " current_qp_state=0x%x, new_qp_state=0x%x\n", + qp_attr_mask, ib_qp->qp_num, ib_qp->qp_type, + curr_qp_state, new_qp_state); + return -EINVAL; + } + dev_dbg(rdev_to_dev(rdev), "%s:%d INFO attribute mask=0x%x qpn=0x%x " + "of type=0x%x current_qp_state=0x%x, new_qp_state=0x%x\n", + __func__, __LINE__, qp_attr_mask, ib_qp->qp_num, + ib_qp->qp_type, curr_qp_state, new_qp_state); + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_STATE; + qp->qplib_qp.state = __from_ib_qp_state(qp_attr->qp_state); + + if (udata && curr_qp_state == IB_QPS_RESET && + new_qp_state == IB_QPS_INIT) { + if (!ib_copy_from_udata(&ureq, udata, sizeof(ureq))) { + if (ureq.comp_mask & + BNXT_RE_COMP_MASK_MQP_EX_PPP_REQ_EN_MASK) { + ppp->req = BNXT_QPLIB_PPP_REQ; + ppp->dpi = ureq.dpi; + } + } + } + } + if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_EN_SQD_ASYNC_NOTIFY; + qp->qplib_qp.en_sqd_async_notify = true; + } + if (qp_attr_mask & IB_QP_ACCESS_FLAGS) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS; + qp->qplib_qp.access = + __from_ib_access_flags(qp_attr->qp_access_flags); + /* LOCAL_WRITE access must be set to allow RC receive */ + qp->qplib_qp.access |= BNXT_QPLIB_ACCESS_LOCAL_WRITE; + qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE; + qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_READ; + } + if (qp_attr_mask & IB_QP_PKEY_INDEX) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY; + qp->qplib_qp.pkey_index = qp_attr->pkey_index; + } + if (qp_attr_mask & IB_QP_QKEY) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY; + qp->qplib_qp.qkey = qp_attr->qkey; + } + if (qp_attr_mask & IB_QP_AV) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_DGID | + CMDQ_MODIFY_QP_MODIFY_MASK_FLOW_LABEL | + CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX | + CMDQ_MODIFY_QP_MODIFY_MASK_HOP_LIMIT | + CMDQ_MODIFY_QP_MODIFY_MASK_TRAFFIC_CLASS | + CMDQ_MODIFY_QP_MODIFY_MASK_DEST_MAC | + CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID; + memcpy(qp->qplib_qp.ah.dgid.data, qp_attr->ah_attr.grh.dgid.raw, + sizeof(qp->qplib_qp.ah.dgid.data)); + qp->qplib_qp.ah.flow_label = qp_attr->ah_attr.grh.flow_label; + qp->qplib_qp.ah.sgid_index = _get_sgid_index(rdev, + qp_attr->ah_attr.grh.sgid_index); + qp->qplib_qp.ah.host_sgid_index = qp_attr->ah_attr.grh.sgid_index; + qp->qplib_qp.ah.hop_limit = qp_attr->ah_attr.grh.hop_limit; + qp->qplib_qp.ah.traffic_class = + qp_attr->ah_attr.grh.traffic_class; + qp->qplib_qp.ah.sl = qp_attr->ah_attr.sl; + ether_addr_copy(qp->qplib_qp.ah.dmac, ROCE_DMAC(&qp_attr->ah_attr)); + sgid_attr = &gid_attr; + status = bnxt_re_get_cached_gid(&rdev->ibdev, 1, + qp_attr->ah_attr.grh.sgid_index, + &sgid, &sgid_attr, + &qp_attr->ah_attr.grh, NULL); + if (!status) + if_rele(sgid_attr->ndev); + gid_ptr = &sgid; + if (sgid_attr->ndev) { + memcpy(qp->qplib_qp.smac, rdev->dev_addr, + ETH_ALEN); + nw_type = bnxt_re_gid_to_network_type(sgid_attr, &sgid); + dev_dbg(rdev_to_dev(rdev), + "Connection using the nw_type %d\n", nw_type); + switch (nw_type) { + case RDMA_NETWORK_IPV4: + qp->qplib_qp.nw_type = + CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV4; + break; + case RDMA_NETWORK_IPV6: + qp->qplib_qp.nw_type = + CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV2_IPV6; + break; + default: + qp->qplib_qp.nw_type = + CMDQ_MODIFY_QP_NETWORK_TYPE_ROCEV1; + break; + } + } + memcpy(&qp->qp_info_entry.sgid, gid_ptr, sizeof(qp->qp_info_entry.sgid)); + } + + /* MTU settings allowed only during INIT -> RTR */ + if (qp_attr->qp_state == IB_QPS_RTR) { + bnxt_re_init_qpmtu(qp, if_getmtu(rdev->netdev), qp_attr_mask, qp_attr, + &is_qpmtu_high); + if (udata && !ib_copy_from_udata(&ureq, udata, sizeof(ureq))) { + if (ureq.comp_mask & BNXT_RE_COMP_MASK_MQP_EX_PATH_MTU_MASK) { + resp.comp_mask |= BNXT_RE_COMP_MASK_MQP_EX_PATH_MTU_MASK; + resp.path_mtu = qp->qplib_qp.mtu; + is_copy_to_udata = true; + } else if (is_qpmtu_high) { + dev_err(rdev_to_dev(rdev), "qp %#x invalid mtu\n", + qp->qplib_qp.id); + return -EINVAL; + } + } + } + + if (qp_attr_mask & IB_QP_TIMEOUT) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_TIMEOUT; + qp->qplib_qp.timeout = qp_attr->timeout; + } + if (qp_attr_mask & IB_QP_RETRY_CNT) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_RETRY_CNT; + qp->qplib_qp.retry_cnt = qp_attr->retry_cnt; + } + if (qp_attr_mask & IB_QP_RNR_RETRY) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_RNR_RETRY; + qp->qplib_qp.rnr_retry = qp_attr->rnr_retry; + } + if (qp_attr_mask & IB_QP_MIN_RNR_TIMER) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER; + qp->qplib_qp.min_rnr_timer = qp_attr->min_rnr_timer; + } + if (qp_attr_mask & IB_QP_RQ_PSN) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_RQ_PSN; + qp->qplib_qp.rq.psn = qp_attr->rq_psn; + } + if (qp_attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_MAX_RD_ATOMIC; + /* Cap the max_rd_atomic to device max */ + if (qp_attr->max_rd_atomic > dev_attr->max_qp_rd_atom) + dev_dbg(rdev_to_dev(rdev), + "max_rd_atomic requested %d is > device max %d\n", + qp_attr->max_rd_atomic, + dev_attr->max_qp_rd_atom); + qp->qplib_qp.max_rd_atomic = min_t(u32, qp_attr->max_rd_atomic, + dev_attr->max_qp_rd_atom); + } + if (qp_attr_mask & IB_QP_SQ_PSN) { + qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN; + qp->qplib_qp.sq.psn = qp_attr->sq_psn; + } + if (qp_attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { + if (qp_attr->max_dest_rd_atomic > + dev_attr->max_qp_init_rd_atom) { + dev_err(rdev_to_dev(rdev), + "max_dest_rd_atomic requested %d is > device max %d\n", + qp_attr->max_dest_rd_atomic, + dev_attr->max_qp_init_rd_atom); + return -EINVAL; + } + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_MAX_DEST_RD_ATOMIC; + qp->qplib_qp.max_dest_rd_atomic = qp_attr->max_dest_rd_atomic; + } + if (qp_attr_mask & IB_QP_CAP) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SIZE | + CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SIZE | + CMDQ_MODIFY_QP_MODIFY_MASK_SQ_SGE | + CMDQ_MODIFY_QP_MODIFY_MASK_RQ_SGE | + CMDQ_MODIFY_QP_MODIFY_MASK_MAX_INLINE_DATA; + if ((qp_attr->cap.max_send_wr >= dev_attr->max_qp_wqes) || + (qp_attr->cap.max_recv_wr >= dev_attr->max_qp_wqes) || + (qp_attr->cap.max_send_sge >= dev_attr->max_qp_sges) || + (qp_attr->cap.max_recv_sge >= dev_attr->max_qp_sges) || + (qp_attr->cap.max_inline_data >= + dev_attr->max_inline_data)) { + dev_err(rdev_to_dev(rdev), + "Create QP failed - max exceeded\n"); + return -EINVAL; + } + entries = roundup_pow_of_two(qp_attr->cap.max_send_wr); + if (entries > dev_attr->max_qp_wqes) + entries = dev_attr->max_qp_wqes; + entries = min_t(u32, entries, dev_attr->max_qp_wqes); + qp->qplib_qp.sq.max_wqe = entries; + qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe - + qp_attr->cap.max_send_wr; + /* + * Reserving one slot for Phantom WQE. Some application can + * post one extra entry in this case. Allowing this to avoid + * unexpected Queue full condition + */ + qp->qplib_qp.sq.q_full_delta -= 1; + qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge; + if (qp->qplib_qp.rq.max_wqe) { + entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr); + if (entries > dev_attr->max_qp_wqes) + entries = dev_attr->max_qp_wqes; + qp->qplib_qp.rq.max_wqe = entries; + qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe - + qp_attr->cap.max_recv_wr; + qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge; + } else { + /* SRQ was used prior, just ignore the RQ caps */ + } + } + if (qp_attr_mask & IB_QP_DEST_QPN) { + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID; + qp->qplib_qp.dest_qpn = qp_attr->dest_qp_num; + } + + rc = bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp); + if (rc) { + dev_err(rdev_to_dev(rdev), "Modify HW QP failed!\n"); + return rc; + } + if (qp_attr_mask & IB_QP_STATE) + bnxt_qplib_manage_flush_qp(qp); + if (ureq.comp_mask & BNXT_RE_COMP_MASK_MQP_EX_PPP_REQ_EN_MASK && + ppp->st_idx_en & CREQ_MODIFY_QP_RESP_PINGPONG_PUSH_ENABLED) { + resp.comp_mask |= BNXT_RE_COMP_MASK_MQP_EX_PPP_REQ_EN; + resp.ppp_st_idx = ppp->st_idx_en >> + BNXT_QPLIB_PPP_ST_IDX_SHIFT; + is_copy_to_udata = true; + } + + if (is_copy_to_udata) { + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) + return rc; + } + + if (ib_qp->qp_type == IB_QPT_GSI && + rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ALL && + rdev->gsi_ctx.gsi_sqp) + rc = bnxt_re_modify_shadow_qp(rdev, qp, qp_attr_mask); + /* + * Update info when qp_info_info + */ + bnxt_re_update_qp_info(rdev, qp); + return rc; +} + +int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, + int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) +{ + struct bnxt_re_qp *qp = to_bnxt_re(ib_qp, struct bnxt_re_qp, ib_qp); + struct bnxt_re_dev *rdev = qp->rdev; + struct bnxt_qplib_qp *qplib_qp; + int rc; + + qplib_qp = kcalloc(1, sizeof(*qplib_qp), GFP_KERNEL); + if (!qplib_qp) + return -ENOMEM; + + qplib_qp->id = qp->qplib_qp.id; + qplib_qp->ah.host_sgid_index = qp->qplib_qp.ah.host_sgid_index; + + rc = bnxt_qplib_query_qp(&rdev->qplib_res, qplib_qp); + if (rc) { + dev_err(rdev_to_dev(rdev), "Query HW QP (0x%x) failed! rc = %d\n", + qplib_qp->id, rc); + goto free_mem; + } + qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state); + qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state); + qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0; + qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access); + qp_attr->pkey_index = qplib_qp->pkey_index; + qp_attr->qkey = qplib_qp->qkey; + memcpy(qp_attr->ah_attr.grh.dgid.raw, qplib_qp->ah.dgid.data, + sizeof(qplib_qp->ah.dgid.data)); + qp_attr->ah_attr.grh.flow_label = qplib_qp->ah.flow_label; + qp_attr->ah_attr.grh.sgid_index = qplib_qp->ah.host_sgid_index; + qp_attr->ah_attr.grh.hop_limit = qplib_qp->ah.hop_limit; + qp_attr->ah_attr.grh.traffic_class = qplib_qp->ah.traffic_class; + qp_attr->ah_attr.sl = qplib_qp->ah.sl; + ether_addr_copy(ROCE_DMAC(&qp_attr->ah_attr), qplib_qp->ah.dmac); + qp_attr->path_mtu = __to_ib_mtu(qplib_qp->path_mtu); + qp_attr->timeout = qplib_qp->timeout; + qp_attr->retry_cnt = qplib_qp->retry_cnt; + qp_attr->rnr_retry = qplib_qp->rnr_retry; + qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer; + qp_attr->rq_psn = qplib_qp->rq.psn; + qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic; + qp_attr->sq_psn = qplib_qp->sq.psn; + qp_attr->max_dest_rd_atomic = qplib_qp->max_dest_rd_atomic; + qp_init_attr->sq_sig_type = qplib_qp->sig_type ? IB_SIGNAL_ALL_WR : + IB_SIGNAL_REQ_WR; + qp_attr->dest_qp_num = qplib_qp->dest_qpn; + + qp_attr->cap.max_send_wr = qp->qplib_qp.sq.max_wqe; + qp_attr->cap.max_send_sge = qp->qplib_qp.sq.max_sge; + qp_attr->cap.max_recv_wr = qp->qplib_qp.rq.max_wqe; + qp_attr->cap.max_recv_sge = qp->qplib_qp.rq.max_sge; + qp_attr->cap.max_inline_data = qp->qplib_qp.max_inline_data; + qp_init_attr->cap = qp_attr->cap; + +free_mem: + kfree(qplib_qp); + return rc; +} + +/* Builders */ + +/* For Raw, the application is responsible to build the entire packet */ +static void bnxt_re_build_raw_send(const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + switch (wr->send_flags) { + case IB_SEND_IP_CSUM: + wqe->rawqp1.lflags |= SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM; + break; + default: + /* Pad HW RoCE iCRC */ + wqe->rawqp1.lflags |= SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC; + break; + } +} + +/* For QP1, the driver must build the entire RoCE (v1/v2) packet hdr + * as according to the sgid and AV + */ +static int bnxt_re_build_qp1_send(struct bnxt_re_qp *qp, const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe, int payload_size) +{ + struct bnxt_re_ah *ah = to_bnxt_re(ud_wr(wr)->ah, struct bnxt_re_ah, + ibah); + struct bnxt_qplib_ah *qplib_ah = &ah->qplib_ah; + struct bnxt_qplib_sge sge; + int i, rc = 0; + union ib_gid sgid; + u16 vlan_id; + u8 *ptmac; + void *buf; + + memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr)); + + /* Get sgid */ + rc = bnxt_re_query_gid(&qp->rdev->ibdev, 1, qplib_ah->sgid_index, &sgid); + if (rc) + return rc; + + /* ETH */ + qp->qp1_hdr.eth_present = 1; + ptmac = ah->qplib_ah.dmac; + memcpy(qp->qp1_hdr.eth.dmac_h, ptmac, 4); + ptmac += 4; + memcpy(qp->qp1_hdr.eth.dmac_l, ptmac, 2); + + ptmac = qp->qplib_qp.smac; + memcpy(qp->qp1_hdr.eth.smac_h, ptmac, 2); + ptmac += 2; + memcpy(qp->qp1_hdr.eth.smac_l, ptmac, 4); + + qp->qp1_hdr.eth.type = cpu_to_be16(BNXT_QPLIB_ETHTYPE_ROCEV1); + + /* For vlan, check the sgid for vlan existence */ + vlan_id = rdma_get_vlan_id(&sgid); + if (vlan_id && vlan_id < 0x1000) { + qp->qp1_hdr.vlan_present = 1; + qp->qp1_hdr.eth.type = cpu_to_be16(ETH_P_8021Q); + } + /* GRH */ + qp->qp1_hdr.grh_present = 1; + qp->qp1_hdr.grh.ip_version = 6; + qp->qp1_hdr.grh.payload_length = + cpu_to_be16((IB_BTH_BYTES + IB_DETH_BYTES + payload_size + 7) + & ~3); + qp->qp1_hdr.grh.next_header = 0x1b; + memcpy(qp->qp1_hdr.grh.source_gid.raw, sgid.raw, sizeof(sgid)); + memcpy(qp->qp1_hdr.grh.destination_gid.raw, qplib_ah->dgid.data, + sizeof(sgid)); + + /* BTH */ + if (wr->opcode == IB_WR_SEND_WITH_IMM) { + qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE; + qp->qp1_hdr.immediate_present = 1; + } else { + qp->qp1_hdr.bth.opcode = IB_OPCODE_UD_SEND_ONLY; + } + if (wr->send_flags & IB_SEND_SOLICITED) + qp->qp1_hdr.bth.solicited_event = 1; + qp->qp1_hdr.bth.pad_count = (4 - payload_size) & 3; + /* P_key for QP1 is for all members */ + qp->qp1_hdr.bth.pkey = cpu_to_be16(0xFFFF); + qp->qp1_hdr.bth.destination_qpn = IB_QP1; + qp->qp1_hdr.bth.ack_req = 0; + qp->send_psn++; + qp->send_psn &= BTH_PSN_MASK; + qp->qp1_hdr.bth.psn = cpu_to_be32(qp->send_psn); + /* DETH */ + /* Use the priviledged Q_Key for QP1 */ + qp->qp1_hdr.deth.qkey = cpu_to_be32(IB_QP1_QKEY); + qp->qp1_hdr.deth.source_qpn = IB_QP1; + + /* Pack the QP1 to the transmit buffer */ + buf = bnxt_qplib_get_qp1_sq_buf(&qp->qplib_qp, &sge); + if (!buf) { + dev_err(rdev_to_dev(qp->rdev), "QP1 buffer is empty!\n"); + rc = -ENOMEM; + } + for (i = wqe->num_sge; i; i--) { + wqe->sg_list[i].addr = wqe->sg_list[i - 1].addr; + wqe->sg_list[i].lkey = wqe->sg_list[i - 1].lkey; + wqe->sg_list[i].size = wqe->sg_list[i - 1].size; + } + wqe->sg_list[0].addr = sge.addr; + wqe->sg_list[0].lkey = sge.lkey; + wqe->sg_list[0].size = sge.size; + wqe->num_sge++; + + return rc; +} + +static int bnxt_re_build_gsi_send(struct bnxt_re_qp *qp, + const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_dev *rdev; + int rc, indx, len = 0; + + rdev = qp->rdev; + + /* Mode UD is applicable to Gen P5 only */ + if (rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_UD) + return 0; + + for (indx = 0; indx < wr->num_sge; indx++) { + wqe->sg_list[indx].addr = wr->sg_list[indx].addr; + wqe->sg_list[indx].lkey = wr->sg_list[indx].lkey; + wqe->sg_list[indx].size = wr->sg_list[indx].length; + len += wr->sg_list[indx].length; + } + rc = bnxt_re_build_qp1_send(qp, wr, wqe, len); + wqe->rawqp1.lflags |= SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC; + + return rc; +} + +/* For the MAD layer, it only provides the recv SGE the size of + ib_grh + MAD datagram. No Ethernet headers, Ethertype, BTH, DETH, + nor RoCE iCRC. The Cu+ solution must provide buffer for the entire + receive packet (334 bytes) with no VLAN and then copy the GRH + and the MAD datagram out to the provided SGE. +*/ + +static int bnxt_re_build_qp1_recv(struct bnxt_re_qp *qp, + const struct ib_recv_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_dev *rdev = qp->rdev; + struct bnxt_qplib_sge ref, sge; + u8 udp_hdr_size = 0; + u8 ip_hdr_size = 0; + int rc = 0; + int size; + + if (bnxt_qplib_get_qp1_rq_buf(&qp->qplib_qp, &sge)) { + /* Create 5 SGEs as according to the following: + * Ethernet header (14) + * ib_grh (40) - as provided from the wr + * ib_bth + ib_deth + UDP(RoCE v2 only) (28) + * MAD (256) - as provided from the wr + * iCRC (4) + */ + + /* Set RoCE v2 header size and offsets */ + if (rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ROCE_V2_IPV4) + ip_hdr_size = 20; + if (rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_ROCE_V1) + udp_hdr_size = 8; + + /* Save the reference from ULP */ + ref.addr = wr->sg_list[0].addr; + ref.lkey = wr->sg_list[0].lkey; + ref.size = wr->sg_list[0].length; + + /* SGE 1 */ + size = sge.size; + wqe->sg_list[0].addr = sge.addr; + wqe->sg_list[0].lkey = sge.lkey; + wqe->sg_list[0].size = BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE; + size -= wqe->sg_list[0].size; + if (size <= 0) { + dev_err(rdev_to_dev(qp->rdev),"QP1 rq buffer is empty!\n"); + rc = -ENOMEM; + goto done; + } + sge.size = (u32)size; + sge.addr += wqe->sg_list[0].size; + + /* SGE 2 */ + /* In case of RoCE v2 ipv4 lower 20 bytes should have IP hdr */ + wqe->sg_list[1].addr = ref.addr + ip_hdr_size; + wqe->sg_list[1].lkey = ref.lkey; + wqe->sg_list[1].size = sizeof(struct ib_grh) - ip_hdr_size; + ref.size -= wqe->sg_list[1].size; + if (ref.size <= 0) { + dev_err(rdev_to_dev(qp->rdev), + "QP1 ref buffer is empty!\n"); + rc = -ENOMEM; + goto done; + } + ref.addr += wqe->sg_list[1].size + ip_hdr_size; + + /* SGE 3 */ + wqe->sg_list[2].addr = sge.addr; + wqe->sg_list[2].lkey = sge.lkey; + wqe->sg_list[2].size = BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE + + udp_hdr_size; + size -= wqe->sg_list[2].size; + if (size <= 0) { + dev_err(rdev_to_dev(qp->rdev), + "QP1 rq buffer is empty!\n"); + rc = -ENOMEM; + goto done; + } + sge.size = (u32)size; + sge.addr += wqe->sg_list[2].size; + + /* SGE 4 */ + wqe->sg_list[3].addr = ref.addr; + wqe->sg_list[3].lkey = ref.lkey; + wqe->sg_list[3].size = ref.size; + ref.size -= wqe->sg_list[3].size; + if (ref.size) { + dev_err(rdev_to_dev(qp->rdev), + "QP1 ref buffer is incorrect!\n"); + rc = -ENOMEM; + goto done; + } + /* SGE 5 */ + wqe->sg_list[4].addr = sge.addr; + wqe->sg_list[4].lkey = sge.lkey; + wqe->sg_list[4].size = sge.size; + size -= wqe->sg_list[4].size; + if (size) { + dev_err(rdev_to_dev(qp->rdev), + "QP1 rq buffer is incorrect!\n"); + rc = -ENOMEM; + goto done; + } + sge.size = (u32)size; + wqe->num_sge = 5; + } else { + dev_err(rdev_to_dev(qp->rdev), "QP1 buffer is empty!\n"); + rc = -ENOMEM; + } +done: + return rc; +} + +static int bnxt_re_build_qp1_shadow_qp_recv(struct bnxt_re_qp *qp, + const struct ib_recv_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_sqp_entries *sqp_entry; + struct bnxt_qplib_sge sge; + struct bnxt_re_dev *rdev; + u32 rq_prod_index; + int rc = 0; + + rdev = qp->rdev; + + rq_prod_index = bnxt_qplib_get_rq_prod_index(&qp->qplib_qp); + + if (bnxt_qplib_get_qp1_rq_buf(&qp->qplib_qp, &sge)) { + /* Create 1 SGE to receive the entire + * ethernet packet + */ + /* SGE 1 */ + wqe->sg_list[0].addr = sge.addr; + /* TODO check the lkey to be used */ + wqe->sg_list[0].lkey = sge.lkey; + wqe->sg_list[0].size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2; + if (sge.size < wqe->sg_list[0].size) { + dev_err(rdev_to_dev(qp->rdev), + "QP1 rq buffer is empty!\n"); + rc = -ENOMEM; + goto done; + } + + sqp_entry = &rdev->gsi_ctx.sqp_tbl[rq_prod_index]; + sqp_entry->sge.addr = wr->sg_list[0].addr; + sqp_entry->sge.lkey = wr->sg_list[0].lkey; + sqp_entry->sge.size = wr->sg_list[0].length; + /* Store the wrid for reporting completion */ + sqp_entry->wrid = wqe->wr_id; + /* change the wqe->wrid to table index */ + wqe->wr_id = rq_prod_index; + } +done: + return rc; +} + +static bool is_ud_qp(struct bnxt_re_qp *qp) +{ + return (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD || + qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_GSI); +} + +static int bnxt_re_build_send_wqe(struct bnxt_re_qp *qp, + const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_ah *ah = NULL; + + if(is_ud_qp(qp)) { + ah = to_bnxt_re(ud_wr(wr)->ah, struct bnxt_re_ah, ibah); + wqe->send.q_key = ud_wr(wr)->remote_qkey; + wqe->send.dst_qp = ud_wr(wr)->remote_qpn; + wqe->send.avid = ah->qplib_ah.id; + } + switch (wr->opcode) { + case IB_WR_SEND: + wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND; + break; + case IB_WR_SEND_WITH_IMM: + wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM; + wqe->send.imm_data = wr->ex.imm_data; + break; + case IB_WR_SEND_WITH_INV: + wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV; + wqe->send.inv_key = wr->ex.invalidate_rkey; + break; + default: + dev_err(rdev_to_dev(qp->rdev), "%s Invalid opcode %d!\n", + __func__, wr->opcode); + return -EINVAL; + } + if (wr->send_flags & IB_SEND_SIGNALED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + if (wr->send_flags & IB_SEND_FENCE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; + if (wr->send_flags & IB_SEND_SOLICITED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT; + if (wr->send_flags & IB_SEND_INLINE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE; + + return 0; +} + +static int bnxt_re_build_rdma_wqe(const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + switch (wr->opcode) { + case IB_WR_RDMA_WRITE: + wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE; + break; + case IB_WR_RDMA_WRITE_WITH_IMM: + wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM; + wqe->rdma.imm_data = wr->ex.imm_data; + break; + case IB_WR_RDMA_READ: + wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_READ; + wqe->rdma.inv_key = wr->ex.invalidate_rkey; + break; + default: + return -EINVAL; + } + wqe->rdma.remote_va = rdma_wr(wr)->remote_addr; + wqe->rdma.r_key = rdma_wr(wr)->rkey; + if (wr->send_flags & IB_SEND_SIGNALED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + if (wr->send_flags & IB_SEND_FENCE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; + if (wr->send_flags & IB_SEND_SOLICITED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT; + if (wr->send_flags & IB_SEND_INLINE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_INLINE; + + return 0; +} + +static int bnxt_re_build_atomic_wqe(const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + switch (wr->opcode) { + case IB_WR_ATOMIC_CMP_AND_SWP: + wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP; + wqe->atomic.cmp_data = atomic_wr(wr)->compare_add; + wqe->atomic.swap_data = atomic_wr(wr)->swap; + break; + case IB_WR_ATOMIC_FETCH_AND_ADD: + wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD; + wqe->atomic.cmp_data = atomic_wr(wr)->compare_add; + break; + default: + return -EINVAL; + } + wqe->atomic.remote_va = atomic_wr(wr)->remote_addr; + wqe->atomic.r_key = atomic_wr(wr)->rkey; + if (wr->send_flags & IB_SEND_SIGNALED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + if (wr->send_flags & IB_SEND_FENCE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; + if (wr->send_flags & IB_SEND_SOLICITED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT; + return 0; +} + +static int bnxt_re_build_inv_wqe(const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + wqe->type = BNXT_QPLIB_SWQE_TYPE_LOCAL_INV; + wqe->local_inv.inv_l_key = wr->ex.invalidate_rkey; + if (wr->send_flags & IB_SEND_SIGNALED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + if (wr->send_flags & IB_SEND_FENCE) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; + if (wr->send_flags & IB_SEND_SOLICITED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT; + + return 0; +} + +static int bnxt_re_build_reg_wqe(const struct ib_reg_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_mr *mr = to_bnxt_re(wr->mr, struct bnxt_re_mr, ib_mr); + struct bnxt_qplib_frpl *qplib_frpl = &mr->qplib_frpl; + int reg_len, i, access = wr->access; + + if (mr->npages > qplib_frpl->max_pg_ptrs) { + dev_err_ratelimited(rdev_to_dev(mr->rdev), + " %s: failed npages %d > %d\n", __func__, + mr->npages, qplib_frpl->max_pg_ptrs); + return -EINVAL; + } + + wqe->frmr.pbl_ptr = (__le64 *)qplib_frpl->hwq.pbl_ptr[0]; + wqe->frmr.pbl_dma_ptr = qplib_frpl->hwq.pbl_dma_ptr[0]; + wqe->frmr.levels = qplib_frpl->hwq.level; + wqe->frmr.page_list = mr->pages; + wqe->frmr.page_list_len = mr->npages; + wqe->type = BNXT_QPLIB_SWQE_TYPE_REG_MR; + + if (wr->wr.send_flags & IB_SEND_SIGNALED) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP; + if (access & IB_ACCESS_LOCAL_WRITE) + wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_LOCAL_WRITE; + if (access & IB_ACCESS_REMOTE_READ) + wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_READ; + if (access & IB_ACCESS_REMOTE_WRITE) + wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_WRITE; + if (access & IB_ACCESS_REMOTE_ATOMIC) + wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_REMOTE_ATOMIC; + if (access & IB_ACCESS_MW_BIND) + wqe->frmr.access_cntl |= SQ_FR_PMR_ACCESS_CNTL_WINDOW_BIND; + + /* TODO: OFED provides the rkey of the MR instead of the lkey */ + wqe->frmr.l_key = wr->key; + wqe->frmr.length = wr->mr->length; + wqe->frmr.pbl_pg_sz_log = ilog2(PAGE_SIZE >> PAGE_SHIFT_4K); + wqe->frmr.pg_sz_log = ilog2(wr->mr->page_size >> PAGE_SHIFT_4K); + wqe->frmr.va = wr->mr->iova; + reg_len = wqe->frmr.page_list_len * wr->mr->page_size; + + if (wqe->frmr.length > reg_len) { + dev_err_ratelimited(rdev_to_dev(mr->rdev), + "%s: bnxt_re_mr 0x%px len (%d > %d)\n", + __func__, (void *)mr, wqe->frmr.length, + reg_len); + + for (i = 0; i < mr->npages; i++) + dev_dbg(rdev_to_dev(mr->rdev), + "%s: build_reg_wqe page[%d] = 0x%llx\n", + __func__, i, mr->pages[i]); + + return -EINVAL; + } + + return 0; +} + +static void bnxt_re_set_sg_list(const struct ib_send_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + wqe->sg_list = (struct bnxt_qplib_sge *)wr->sg_list; + wqe->num_sge = wr->num_sge; +} + +static void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp) +{ + if ((qp->ib_qp.qp_type == IB_QPT_UD || qp->ib_qp.qp_type == IB_QPT_GSI || + qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) && + qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) { + int qp_attr_mask; + struct ib_qp_attr qp_attr; + + qp_attr_mask = IB_QP_STATE; + qp_attr.qp_state = IB_QPS_RTS; + bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL); + qp->qplib_qp.wqe_cnt = 0; + } +} + +static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp, + const struct ib_send_wr *wr) +{ + struct bnxt_qplib_swqe wqe; + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&qp->sq_lock, flags); + while (wr) { + /* House keeping */ + memset(&wqe, 0, sizeof(wqe)); + /* Common */ + if (wr->num_sge > qp->qplib_qp.sq.max_sge) { + dev_err(rdev_to_dev(rdev), + "Limit exceeded for Send SGEs\n"); + rc = -EINVAL; + break; + } + + bnxt_re_set_sg_list(wr, &wqe); + wqe.wr_id = wr->wr_id; + wqe.type = BNXT_QPLIB_SWQE_TYPE_SEND; + rc = bnxt_re_build_send_wqe(qp, wr, &wqe); + if (rc) + break; + + rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe); + if (rc) { + dev_err(rdev_to_dev(rdev), + "bad_wr seen with opcode = 0x%x rc = %d\n", + wr->opcode, rc); + break; + } + wr = wr->next; + } + bnxt_qplib_post_send_db(&qp->qplib_qp); + bnxt_ud_qp_hw_stall_workaround(qp); + spin_unlock_irqrestore(&qp->sq_lock, flags); + return rc; +} + +static void bnxt_re_legacy_set_uc_fence(struct bnxt_qplib_swqe *wqe) +{ + /* Need unconditional fence for non-wire memory opcode + * to work as expected. + */ + if (wqe->type == BNXT_QPLIB_SWQE_TYPE_LOCAL_INV || + wqe->type == BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR || + wqe->type == BNXT_QPLIB_SWQE_TYPE_REG_MR || + wqe->type == BNXT_QPLIB_SWQE_TYPE_BIND_MW) + wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE; +} + +int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr) +{ + struct bnxt_re_qp *qp = to_bnxt_re(ib_qp, struct bnxt_re_qp, ib_qp); + struct bnxt_qplib_sge sge[6]; + struct bnxt_qplib_swqe wqe; + struct bnxt_re_dev *rdev; + unsigned long flags; + int rc = 0; + + rdev = qp->rdev; + spin_lock_irqsave(&qp->sq_lock, flags); + while (wr) { + /* House keeping */ + memset(&wqe, 0, sizeof(wqe)); + /* Common */ + if (wr->num_sge > qp->qplib_qp.sq.max_sge) { + dev_err(rdev_to_dev(rdev), + "Limit exceeded for Send SGEs\n"); + rc = -EINVAL; + goto bad; + } + + bnxt_re_set_sg_list(wr, &wqe); + wqe.wr_id = wr->wr_id; + + switch (wr->opcode) { + case IB_WR_SEND: + case IB_WR_SEND_WITH_IMM: + if (ib_qp->qp_type == IB_QPT_GSI && + rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_UD) { + memset(sge, 0, sizeof(sge)); + wqe.sg_list = sge; + rc = bnxt_re_build_gsi_send(qp, wr, &wqe); + if (rc) + goto bad; + } else if (ib_qp->qp_type == IB_QPT_RAW_ETHERTYPE) { + bnxt_re_build_raw_send(wr, &wqe); + } + switch (wr->send_flags) { + case IB_SEND_IP_CSUM: + wqe.rawqp1.lflags |= + SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM; + break; + default: + break; + } + fallthrough; + case IB_WR_SEND_WITH_INV: + rc = bnxt_re_build_send_wqe(qp, wr, &wqe); + break; + case IB_WR_RDMA_WRITE: + case IB_WR_RDMA_WRITE_WITH_IMM: + case IB_WR_RDMA_READ: + rc = bnxt_re_build_rdma_wqe(wr, &wqe); + break; + case IB_WR_ATOMIC_CMP_AND_SWP: + case IB_WR_ATOMIC_FETCH_AND_ADD: + rc = bnxt_re_build_atomic_wqe(wr, &wqe); + break; + case IB_WR_RDMA_READ_WITH_INV: + dev_err(rdev_to_dev(rdev), + "RDMA Read with Invalidate is not supported\n"); + rc = -EINVAL; + goto bad; + case IB_WR_LOCAL_INV: + rc = bnxt_re_build_inv_wqe(wr, &wqe); + break; + case IB_WR_REG_MR: + rc = bnxt_re_build_reg_wqe(reg_wr(wr), &wqe); + break; + default: + /* Unsupported WRs */ + dev_err(rdev_to_dev(rdev), + "WR (0x%x) is not supported\n", wr->opcode); + rc = -EINVAL; + goto bad; + } + + if (likely(!rc)) { + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + bnxt_re_legacy_set_uc_fence(&wqe); + rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe); + } +bad: + if (unlikely(rc)) { + dev_err(rdev_to_dev(rdev), + "bad_wr seen with opcode = 0x%x\n", wr->opcode); + *bad_wr = wr; + break; + } + wr = wr->next; + } + bnxt_qplib_post_send_db(&qp->qplib_qp); + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + bnxt_ud_qp_hw_stall_workaround(qp); + spin_unlock_irqrestore(&qp->sq_lock, flags); + + return rc; +} + +static int bnxt_re_post_recv_shadow_qp(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp, + struct ib_recv_wr *wr) +{ + struct bnxt_qplib_swqe wqe; + int rc = 0; + + /* rq lock can be pardoned here. */ + while (wr) { + /* House keeping */ + memset(&wqe, 0, sizeof(wqe)); + /* Common */ + if (wr->num_sge > qp->qplib_qp.rq.max_sge) { + dev_err(rdev_to_dev(rdev), + "Limit exceeded for Receive SGEs\n"); + rc = -EINVAL; + goto bad; + } + + wqe.sg_list = (struct bnxt_qplib_sge *)wr->sg_list; + wqe.num_sge = wr->num_sge; + wqe.wr_id = wr->wr_id; + wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV; + rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe); +bad: + if (rc) { + dev_err(rdev_to_dev(rdev), + "bad_wr seen with RQ post\n"); + break; + } + wr = wr->next; + } + bnxt_qplib_post_recv_db(&qp->qplib_qp); + return rc; +} + +static int bnxt_re_build_gsi_recv(struct bnxt_re_qp *qp, + const struct ib_recv_wr *wr, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_re_dev *rdev = qp->rdev; + int rc = 0; + + if (rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ALL) + rc = bnxt_re_build_qp1_shadow_qp_recv(qp, wr, wqe); + else + rc = bnxt_re_build_qp1_recv(qp, wr, wqe); + + return rc; +} + +int bnxt_re_post_recv(struct ib_qp *ib_qp, const struct ib_recv_wr *wr, + const struct ib_recv_wr **bad_wr) +{ + struct bnxt_re_qp *qp = to_bnxt_re(ib_qp, struct bnxt_re_qp, ib_qp); + struct bnxt_qplib_sge sge[6]; + struct bnxt_qplib_swqe wqe; + unsigned long flags; + u32 count = 0; + int rc = 0; + + spin_lock_irqsave(&qp->rq_lock, flags); + while (wr) { + memset(&wqe, 0, sizeof(wqe)); + if (wr->num_sge > qp->qplib_qp.rq.max_sge) { + dev_err(rdev_to_dev(qp->rdev), + "Limit exceeded for Receive SGEs\n"); + rc = -EINVAL; + goto bad; + } + wqe.num_sge = wr->num_sge; + wqe.sg_list = (struct bnxt_qplib_sge *)wr->sg_list; + wqe.wr_id = wr->wr_id; + wqe.type = BNXT_QPLIB_SWQE_TYPE_RECV; + + if (ib_qp->qp_type == IB_QPT_GSI && + qp->rdev->gsi_ctx.gsi_qp_mode != BNXT_RE_GSI_MODE_UD) { + memset(sge, 0, sizeof(sge)); + wqe.sg_list = sge; + rc = bnxt_re_build_gsi_recv(qp, wr, &wqe); + if (rc) + goto bad; + } + rc = bnxt_qplib_post_recv(&qp->qplib_qp, &wqe); +bad: + if (rc) { + dev_err(rdev_to_dev(qp->rdev), + "bad_wr seen with RQ post\n"); + *bad_wr = wr; + break; + } + /* Ring DB if the RQEs posted reaches a threshold value */ + if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) { + bnxt_qplib_post_recv_db(&qp->qplib_qp); + count = 0; + } + wr = wr->next; + } + + if (count) + bnxt_qplib_post_recv_db(&qp->qplib_qp); + spin_unlock_irqrestore(&qp->rq_lock, flags); + + return rc; +} + +/* Completion Queues */ +void bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata) +{ + struct bnxt_re_cq *cq = to_bnxt_re(ib_cq, struct bnxt_re_cq, ibcq); + struct bnxt_re_dev *rdev = cq->rdev; + int rc = 0; + + if (cq->uctx_cq_page) { + BNXT_RE_CQ_PAGE_LIST_DEL(cq->uctx, cq); + free_page((u64)cq->uctx_cq_page); + cq->uctx_cq_page = NULL; + } + if (cq->is_dbr_soft_cq && cq->uctx) { + void *dbr_page; + + if (cq->uctx->dbr_recov_cq) { + dbr_page = cq->uctx->dbr_recov_cq_page; + cq->uctx->dbr_recov_cq_page = NULL; + cq->uctx->dbr_recov_cq = NULL; + free_page((unsigned long)dbr_page); + } + goto end; + } + /* CQ getting destroyed. Set this state for cqn handler */ + spin_lock_bh(&cq->qplib_cq.compl_lock); + cq->qplib_cq.destroyed = true; + spin_unlock_bh(&cq->qplib_cq.compl_lock); + if (ib_cq->poll_ctx == IB_POLL_WORKQUEUE || + ib_cq->poll_ctx == IB_POLL_UNBOUND_WORKQUEUE) + cancel_work_sync(&ib_cq->work); + + rc = bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq); + if (rc) + dev_err_ratelimited(rdev_to_dev(rdev), + "%s id = %d failed rc = %d\n", + __func__, cq->qplib_cq.id, rc); + + bnxt_re_put_nq(rdev, cq->qplib_cq.nq); + if (cq->umem && !IS_ERR(cq->umem)) + ib_umem_release(cq->umem); + + kfree(cq->cql); + atomic_dec(&rdev->stats.rsors.cq_count); +end: + return; +} + +static inline struct +bnxt_re_cq *__get_cq_from_cq_in(struct ib_cq *cq_in, + struct bnxt_re_dev *rdev) +{ + struct bnxt_re_cq *cq; + cq = container_of(cq_in, struct bnxt_re_cq, ibcq); + return cq; +} + +int bnxt_re_create_cq(struct ib_cq *cq_in, + const struct ib_cq_init_attr *attr, + struct ib_udata *udata) +{ + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_re_ucontext *uctx = NULL; + struct ib_ucontext *context = NULL; + struct bnxt_qplib_cq *qplcq; + struct bnxt_re_cq_req ureq; + struct bnxt_re_dev *rdev; + int rc, entries; + struct bnxt_re_cq *cq; + u32 max_active_cqs; + int cqe = attr->cqe; + + if (attr->flags) + return -EOPNOTSUPP; + + rdev = rdev_from_cq_in(cq_in); + if (rdev->mod_exit) { + rc = -EIO; + dev_dbg(rdev_to_dev(rdev), "%s(): in mod_exit, just return!\n", __func__); + goto exit; + } + if (udata) { + uctx = rdma_udata_to_drv_context(udata, + struct bnxt_re_ucontext, + ibucontext); + context = &uctx->ibucontext; + } + dev_attr = rdev->dev_attr; + + if (atomic_read(&rdev->stats.rsors.cq_count) >= dev_attr->max_cq) { + dev_err(rdev_to_dev(rdev), "Create CQ failed - max exceeded(CQs)\n"); + rc = -EINVAL; + goto exit; + } + /* Validate CQ fields */ + if (cqe < 1 || cqe > dev_attr->max_cq_wqes) { + dev_err(rdev_to_dev(rdev), "Create CQ failed - max exceeded(CQ_WQs)\n"); + rc = -EINVAL; + goto exit; + } + + cq = __get_cq_from_cq_in(cq_in, rdev); + if (!cq) { + rc = -ENOMEM; + goto exit; + } + cq->rdev = rdev; + cq->uctx = uctx; + qplcq = &cq->qplib_cq; + qplcq->cq_handle = (u64)qplcq; + /* + * Since CQ is for QP1 is shared with Shadow CQ, the size + * should be double the size. There is no way to identify + * whether this CQ is for GSI QP. So assuming that the first + * CQ created is for QP1 + */ + if (!udata && !rdev->gsi_ctx.first_cq_created && + rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ALL) { + rdev->gsi_ctx.first_cq_created = true; + /* + * Total CQE required for the CQ = CQE for QP1 RQ + + * CQE for Shadow QP SQEs + CQE for Shadow QP RQEs. + * Max entries of shadow QP SQ and RQ = QP1 RQEs = cqe + */ + cqe *= 3; + } + + entries = bnxt_re_init_depth(cqe + 1, uctx); + if (entries > dev_attr->max_cq_wqes + 1) + entries = dev_attr->max_cq_wqes + 1; + + qplcq->sginfo.pgshft = PAGE_SHIFT; + qplcq->sginfo.pgsize = PAGE_SIZE; + if (udata) { + if (udata->inlen < sizeof(ureq)) + dev_warn(rdev_to_dev(rdev), + "Update the library ulen %d klen %d\n", + (unsigned int)udata->inlen, + (unsigned int)sizeof(ureq)); + + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + goto fail; + + if (BNXT_RE_IS_DBR_PACING_NOTIFY_CQ(ureq)) { + cq->is_dbr_soft_cq = true; + goto success; + } + + if (BNXT_RE_IS_DBR_RECOV_CQ(ureq)) { + void *dbr_page; + u32 *epoch; + + dbr_page = (void *)__get_free_page(GFP_KERNEL); + if (!dbr_page) { + dev_err(rdev_to_dev(rdev), + "DBR recov CQ page allocation failed!"); + rc = -ENOMEM; + goto fail; + } + + /* memset the epoch and epoch_ack to 0 */ + epoch = dbr_page; + epoch[0] = 0x0; + epoch[1] = 0x0; + + uctx->dbr_recov_cq = cq; + uctx->dbr_recov_cq_page = dbr_page; + + cq->is_dbr_soft_cq = true; + goto success; + } + + cq->umem = ib_umem_get_compat + (rdev, context, udata, ureq.cq_va, + entries * sizeof(struct cq_base), + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(cq->umem)) { + rc = PTR_ERR(cq->umem); + dev_err(rdev_to_dev(rdev), + "%s: ib_umem_get failed! rc = %d\n", + __func__, rc); + goto fail; + } + qplcq->sginfo.sghead = get_ib_umem_sgl(cq->umem, + &qplcq->sginfo.nmap); + qplcq->sginfo.npages = ib_umem_num_pages_compat(cq->umem); + if (!uctx->dpi.dbr) { + rc = bnxt_re_get_user_dpi(rdev, uctx); + if (rc) + goto c2fail; + } + qplcq->dpi = &uctx->dpi; + } else { + cq->max_cql = entries > MAX_CQL_PER_POLL ? MAX_CQL_PER_POLL : entries; + cq->cql = kcalloc(cq->max_cql, sizeof(struct bnxt_qplib_cqe), + GFP_KERNEL); + if (!cq->cql) { + dev_err(rdev_to_dev(rdev), + "Allocate CQL for %d failed!\n", cq->max_cql); + rc = -ENOMEM; + goto fail; + } + qplcq->dpi = &rdev->dpi_privileged; + } + /* + * Allocating the NQ in a round robin fashion. nq_alloc_cnt is a + * used for getting the NQ index. + */ + qplcq->max_wqe = entries; + qplcq->nq = bnxt_re_get_nq(rdev); + qplcq->cnq_hw_ring_id = qplcq->nq->ring_id; + + rc = bnxt_qplib_create_cq(&rdev->qplib_res, qplcq); + if (rc) { + dev_err(rdev_to_dev(rdev), "Create HW CQ failed!\n"); + goto fail; + } + + INIT_LIST_HEAD(&cq->cq_list); + cq->ibcq.cqe = entries; + cq->cq_period = qplcq->period; + + atomic_inc(&rdev->stats.rsors.cq_count); + max_active_cqs = atomic_read(&rdev->stats.rsors.cq_count); + if (max_active_cqs > atomic_read(&rdev->stats.rsors.max_cq_count)) + atomic_set(&rdev->stats.rsors.max_cq_count, max_active_cqs); + spin_lock_init(&cq->cq_lock); + + if (udata) { + struct bnxt_re_cq_resp resp; + + resp.cqid = qplcq->id; + resp.tail = qplcq->hwq.cons; + resp.phase = qplcq->period; + resp.comp_mask = 0; + resp.dbr = (u64)uctx->dpi.umdbr; + resp.dpi = uctx->dpi.dpi; + resp.comp_mask |= BNXT_RE_COMP_MASK_CQ_HAS_DB_INFO; + /* Copy only on a valid wcpdi */ + if (uctx->wcdpi.dpi) { + resp.wcdpi = uctx->wcdpi.dpi; + resp.comp_mask |= BNXT_RE_COMP_MASK_CQ_HAS_WC_DPI; + } + + if (_is_chip_p7(rdev->chip_ctx)) { + cq->uctx_cq_page = (void *)__get_free_page(GFP_KERNEL); + + if (!cq->uctx_cq_page) { + dev_err(rdev_to_dev(rdev), + "CQ page allocation failed!\n"); + bnxt_qplib_destroy_cq(&rdev->qplib_res, qplcq); + rc = -ENOMEM; + goto c2fail; + } + + resp.uctx_cq_page = (u64)cq->uctx_cq_page; + resp.comp_mask |= BNXT_RE_COMP_MASK_CQ_HAS_CQ_PAGE; + } + + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) { + free_page((u64)cq->uctx_cq_page); + cq->uctx_cq_page = NULL; + bnxt_qplib_destroy_cq(&rdev->qplib_res, qplcq); + goto c2fail; + } + + if (cq->uctx_cq_page) + BNXT_RE_CQ_PAGE_LIST_ADD(uctx, cq); + } + +success: + return 0; +c2fail: + if (udata && cq->umem && !IS_ERR(cq->umem)) + ib_umem_release(cq->umem); +fail: + if (cq) { + if (cq->cql) + kfree(cq->cql); + } +exit: + return rc; +} + +int bnxt_re_modify_cq(struct ib_cq *ib_cq, u16 cq_count, u16 cq_period) +{ + struct bnxt_re_cq *cq = to_bnxt_re(ib_cq, struct bnxt_re_cq, ibcq); + struct bnxt_re_dev *rdev = cq->rdev; + int rc; + + if ((cq->cq_count != cq_count) || (cq->cq_period != cq_period)) { + cq->qplib_cq.count = cq_count; + cq->qplib_cq.period = cq_period; + rc = bnxt_qplib_modify_cq(&rdev->qplib_res, &cq->qplib_cq); + if (rc) { + dev_err(rdev_to_dev(rdev), "Modify HW CQ %#x failed!\n", + cq->qplib_cq.id); + return rc; + } + /* On success, update the shadow */ + cq->cq_count = cq_count; + cq->cq_period = cq_period; + } + return 0; +} + +static void bnxt_re_resize_cq_complete(struct bnxt_re_cq *cq) +{ + struct bnxt_re_dev *rdev = cq->rdev; + + bnxt_qplib_resize_cq_complete(&rdev->qplib_res, &cq->qplib_cq); + + cq->qplib_cq.max_wqe = cq->resize_cqe; + if (cq->resize_umem) { + ib_umem_release(cq->umem); + cq->umem = cq->resize_umem; + cq->resize_umem = NULL; + cq->resize_cqe = 0; + } +} + +int bnxt_re_resize_cq(struct ib_cq *ib_cq, int cqe, struct ib_udata *udata) +{ + struct bnxt_qplib_sg_info sginfo = {}; + struct bnxt_qplib_dpi *orig_dpi = NULL; + struct bnxt_qplib_dev_attr *dev_attr; + struct bnxt_re_ucontext *uctx = NULL; + struct bnxt_re_resize_cq_req ureq; + struct ib_ucontext *context = NULL; + struct bnxt_re_dev *rdev; + struct bnxt_re_cq *cq; + int rc, entries; + + /* Don't allow more than one resize request at the same time. + * TODO: need a mutex here when we support kernel consumers of resize. + */ + cq = to_bnxt_re(ib_cq, struct bnxt_re_cq, ibcq); + rdev = cq->rdev; + dev_attr = rdev->dev_attr; + if (ib_cq->uobject) { + uctx = rdma_udata_to_drv_context(udata, + struct bnxt_re_ucontext, + ibucontext); + context = &uctx->ibucontext; + } + + if (cq->resize_umem) { + dev_err(rdev_to_dev(rdev), "Resize CQ %#x failed - Busy\n", + cq->qplib_cq.id); + return -EBUSY; + } + + /* Check the requested cq depth out of supported depth */ + if (cqe < 1 || cqe > dev_attr->max_cq_wqes) { + dev_err(rdev_to_dev(rdev), "Resize CQ %#x failed - max exceeded\n", + cq->qplib_cq.id); + return -EINVAL; + } + + entries = bnxt_re_init_depth(cqe + 1, uctx); + entries = min_t(u32, (u32)entries, dev_attr->max_cq_wqes + 1); + + /* Check to see if the new requested size can be handled by already + * existing CQ + */ + if (entries == cq->ibcq.cqe) { + dev_info(rdev_to_dev(rdev), "CQ is already at size %d\n", cqe); + return 0; + } + + if (ib_cq->uobject && udata) { + if (udata->inlen < sizeof(ureq)) + dev_warn(rdev_to_dev(rdev), + "Update the library ulen %d klen %d\n", + (unsigned int)udata->inlen, + (unsigned int)sizeof(ureq)); + + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + goto fail; + + dev_dbg(rdev_to_dev(rdev), "%s: va %p\n", __func__, + (void *)ureq.cq_va); + cq->resize_umem = ib_umem_get_compat + (rdev, + context, udata, ureq.cq_va, + entries * sizeof(struct cq_base), + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(cq->resize_umem)) { + rc = PTR_ERR(cq->resize_umem); + cq->resize_umem = NULL; + dev_err(rdev_to_dev(rdev), "%s: ib_umem_get failed! rc = %d\n", + __func__, rc); + goto fail; + } + cq->resize_cqe = entries; + dev_dbg(rdev_to_dev(rdev), "%s: ib_umem_get() success\n", + __func__); + memcpy(&sginfo, &cq->qplib_cq.sginfo, sizeof(sginfo)); + orig_dpi = cq->qplib_cq.dpi; + + cq->qplib_cq.sginfo.sghead = get_ib_umem_sgl(cq->resize_umem, + &cq->qplib_cq.sginfo.nmap); + cq->qplib_cq.sginfo.npages = + ib_umem_num_pages_compat(cq->resize_umem); + cq->qplib_cq.sginfo.pgsize = PAGE_SIZE; + cq->qplib_cq.sginfo.pgshft = PAGE_SHIFT; + cq->qplib_cq.dpi = &uctx->dpi; + } else { + /* TODO: kernel consumer */ + } + + rc = bnxt_qplib_resize_cq(&rdev->qplib_res, &cq->qplib_cq, entries); + if (rc) { + dev_err(rdev_to_dev(rdev), "Resize HW CQ %#x failed!\n", + cq->qplib_cq.id); + goto fail; + } + + cq->ibcq.cqe = cq->resize_cqe; + /* For kernel consumers complete resize here. For uverbs consumers, + * we complete it in the context of ibv_poll_cq(). + */ + if (!cq->resize_umem) + bnxt_qplib_resize_cq_complete(&rdev->qplib_res, &cq->qplib_cq); + + atomic_inc(&rdev->stats.rsors.resize_count); + return 0; + +fail: + if (cq->resize_umem) { + ib_umem_release(cq->resize_umem); + cq->resize_umem = NULL; + cq->resize_cqe = 0; + memcpy(&cq->qplib_cq.sginfo, &sginfo, sizeof(sginfo)); + cq->qplib_cq.dpi = orig_dpi; + } + return rc; +} + +static enum ib_wc_status __req_to_ib_wc_status(u8 qstatus) +{ + switch(qstatus) { + case CQ_REQ_STATUS_OK: + return IB_WC_SUCCESS; + case CQ_REQ_STATUS_BAD_RESPONSE_ERR: + return IB_WC_BAD_RESP_ERR; + case CQ_REQ_STATUS_LOCAL_LENGTH_ERR: + return IB_WC_LOC_LEN_ERR; + case CQ_REQ_STATUS_LOCAL_QP_OPERATION_ERR: + return IB_WC_LOC_QP_OP_ERR; + case CQ_REQ_STATUS_LOCAL_PROTECTION_ERR: + return IB_WC_LOC_PROT_ERR; + case CQ_REQ_STATUS_MEMORY_MGT_OPERATION_ERR: + return IB_WC_GENERAL_ERR; + case CQ_REQ_STATUS_REMOTE_INVALID_REQUEST_ERR: + return IB_WC_REM_INV_REQ_ERR; + case CQ_REQ_STATUS_REMOTE_ACCESS_ERR: + return IB_WC_REM_ACCESS_ERR; + case CQ_REQ_STATUS_REMOTE_OPERATION_ERR: + return IB_WC_REM_OP_ERR; + case CQ_REQ_STATUS_RNR_NAK_RETRY_CNT_ERR: + return IB_WC_RNR_RETRY_EXC_ERR; + case CQ_REQ_STATUS_TRANSPORT_RETRY_CNT_ERR: + return IB_WC_RETRY_EXC_ERR; + case CQ_REQ_STATUS_WORK_REQUEST_FLUSHED_ERR: + return IB_WC_WR_FLUSH_ERR; + default: + return IB_WC_GENERAL_ERR; + } + return 0; +} + +static enum ib_wc_status __rawqp1_to_ib_wc_status(u8 qstatus) +{ + switch(qstatus) { + case CQ_RES_RAWETH_QP1_STATUS_OK: + return IB_WC_SUCCESS; + case CQ_RES_RAWETH_QP1_STATUS_LOCAL_ACCESS_ERROR: + return IB_WC_LOC_ACCESS_ERR; + case CQ_RES_RAWETH_QP1_STATUS_HW_LOCAL_LENGTH_ERR: + return IB_WC_LOC_LEN_ERR; + case CQ_RES_RAWETH_QP1_STATUS_LOCAL_PROTECTION_ERR: + return IB_WC_LOC_PROT_ERR; + case CQ_RES_RAWETH_QP1_STATUS_LOCAL_QP_OPERATION_ERR: + return IB_WC_LOC_QP_OP_ERR; + case CQ_RES_RAWETH_QP1_STATUS_MEMORY_MGT_OPERATION_ERR: + return IB_WC_GENERAL_ERR; + case CQ_RES_RAWETH_QP1_STATUS_WORK_REQUEST_FLUSHED_ERR: + return IB_WC_WR_FLUSH_ERR; + case CQ_RES_RAWETH_QP1_STATUS_HW_FLUSH_ERR: + return IB_WC_WR_FLUSH_ERR; + default: + return IB_WC_GENERAL_ERR; + } +} + +static enum ib_wc_status __rc_to_ib_wc_status(u8 qstatus) +{ + switch(qstatus) { + case CQ_RES_RC_STATUS_OK: + return IB_WC_SUCCESS; + case CQ_RES_RC_STATUS_LOCAL_ACCESS_ERROR: + return IB_WC_LOC_ACCESS_ERR; + case CQ_RES_RC_STATUS_LOCAL_LENGTH_ERR: + return IB_WC_LOC_LEN_ERR; + case CQ_RES_RC_STATUS_LOCAL_PROTECTION_ERR: + return IB_WC_LOC_PROT_ERR; + case CQ_RES_RC_STATUS_LOCAL_QP_OPERATION_ERR: + return IB_WC_LOC_QP_OP_ERR; + case CQ_RES_RC_STATUS_MEMORY_MGT_OPERATION_ERR: + return IB_WC_GENERAL_ERR; + case CQ_RES_RC_STATUS_REMOTE_INVALID_REQUEST_ERR: + return IB_WC_REM_INV_REQ_ERR; + case CQ_RES_RC_STATUS_WORK_REQUEST_FLUSHED_ERR: + return IB_WC_WR_FLUSH_ERR; + case CQ_RES_RC_STATUS_HW_FLUSH_ERR: + return IB_WC_WR_FLUSH_ERR; + default: + return IB_WC_GENERAL_ERR; + } +} + +static void bnxt_re_process_req_wc(struct ib_wc *wc, struct bnxt_qplib_cqe *cqe) +{ + switch (cqe->type) { + case BNXT_QPLIB_SWQE_TYPE_SEND: + wc->opcode = IB_WC_SEND; + break; + case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM: + wc->opcode = IB_WC_SEND; + wc->wc_flags |= IB_WC_WITH_IMM; + break; + case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV: + wc->opcode = IB_WC_SEND; + wc->wc_flags |= IB_WC_WITH_INVALIDATE; + break; + case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE: + wc->opcode = IB_WC_RDMA_WRITE; + break; + case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM: + wc->opcode = IB_WC_RDMA_WRITE; + wc->wc_flags |= IB_WC_WITH_IMM; + break; + case BNXT_QPLIB_SWQE_TYPE_RDMA_READ: + wc->opcode = IB_WC_RDMA_READ; + break; + case BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP: + wc->opcode = IB_WC_COMP_SWAP; + break; + case BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD: + wc->opcode = IB_WC_FETCH_ADD; + break; + case BNXT_QPLIB_SWQE_TYPE_LOCAL_INV: + wc->opcode = IB_WC_LOCAL_INV; + break; + case BNXT_QPLIB_SWQE_TYPE_REG_MR: + wc->opcode = IB_WC_REG_MR; + break; + default: + wc->opcode = IB_WC_SEND; + break; + } + + wc->status = __req_to_ib_wc_status(cqe->status); +} + +static int bnxt_re_check_packet_type(u16 raweth_qp1_flags, u16 raweth_qp1_flags2) +{ + bool is_ipv6 = false, is_ipv4 = false; + + /* raweth_qp1_flags Bit 9-6 indicates itype */ + + if ((raweth_qp1_flags & CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE) + != CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS_ITYPE_ROCE) + return -1; + + if (raweth_qp1_flags2 & + CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_CS_CALC && + raweth_qp1_flags2 & + CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_L4_CS_CALC) { + /* raweth_qp1_flags2 Bit 8 indicates ip_type. 0-v4 1 - v6 */ + (raweth_qp1_flags2 & + CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_IP_TYPE) ? + (is_ipv6 = true) : (is_ipv4 = true); + return ((is_ipv6) ? + BNXT_RE_ROCEV2_IPV6_PACKET : + BNXT_RE_ROCEV2_IPV4_PACKET); + } else { + return BNXT_RE_ROCE_V1_PACKET; + } +} + +static bool bnxt_re_is_loopback_packet(struct bnxt_re_dev *rdev, + void *rq_hdr_buf) +{ + u8 *tmp_buf = NULL; + struct ethhdr *eth_hdr; + u16 eth_type; + bool rc = false; + + tmp_buf = (u8 *)rq_hdr_buf; + /* + * If dest mac is not same as I/F mac, this could be a + * loopback address or multicast address, check whether + * it is a loopback packet + */ + if (!ether_addr_equal(tmp_buf, rdev->dev_addr)) { + tmp_buf += 4; + /* Check the ether type */ + eth_hdr = (struct ethhdr *)tmp_buf; + eth_type = ntohs(eth_hdr->h_proto); + switch (eth_type) { + case BNXT_QPLIB_ETHTYPE_ROCEV1: + rc = true; + break; + default: + break; + } + } + + return rc; +} + +static bool bnxt_re_is_vlan_in_packet(struct bnxt_re_dev *rdev, + void *rq_hdr_buf, + struct bnxt_qplib_cqe *cqe) +{ + struct vlan_hdr *vlan_hdr; + struct ethhdr *eth_hdr; + u8 *tmp_buf = NULL; + u16 eth_type; + + tmp_buf = (u8 *)rq_hdr_buf; + /* Check the ether type */ + eth_hdr = (struct ethhdr *)tmp_buf; + eth_type = ntohs(eth_hdr->h_proto); + if (eth_type == ETH_P_8021Q) { + tmp_buf += sizeof(struct ethhdr); + vlan_hdr = (struct vlan_hdr *)tmp_buf; + cqe->raweth_qp1_metadata = + ntohs(vlan_hdr->h_vlan_TCI) | + (eth_type << + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_SFT); + cqe->raweth_qp1_flags2 |= + CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_VLAN; + return true; + } + + return false; +} + +static int bnxt_re_process_raw_qp_packet_receive(struct bnxt_re_qp *gsi_qp, + struct bnxt_qplib_cqe *cqe) +{ + struct bnxt_re_sqp_entries *sqp_entry = NULL; + struct bnxt_qplib_hdrbuf *hdr_buf; + dma_addr_t shrq_hdr_buf_map; + struct ib_sge s_sge[2] = {}; + struct ib_sge r_sge[2] = {}; + struct ib_recv_wr rwr = {}; + struct bnxt_re_ah *gsi_sah; + struct bnxt_re_qp *gsi_sqp; + dma_addr_t rq_hdr_buf_map; + struct bnxt_re_dev *rdev; + struct ib_send_wr *swr; + u32 skip_bytes = 0; + void *rq_hdr_buf; + int pkt_type = 0; + u32 offset = 0; + u32 tbl_idx; + int rc; + struct ib_ud_wr udwr = {}; + + swr = &udwr.wr; + rdev = gsi_qp->rdev; + gsi_sqp = rdev->gsi_ctx.gsi_sqp; + tbl_idx = cqe->wr_id; + + hdr_buf = gsi_qp->qplib_qp.rq_hdr_buf; + rq_hdr_buf = (u8 *) hdr_buf->va + tbl_idx * hdr_buf->step; + rq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp, + tbl_idx); + /* Shadow QP header buffer */ + shrq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_sqp->qplib_qp, + tbl_idx); + sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx]; + + /* Find packet type from the cqe */ + pkt_type = bnxt_re_check_packet_type(cqe->raweth_qp1_flags, + cqe->raweth_qp1_flags2); + if (pkt_type < 0) { + dev_err(rdev_to_dev(rdev), "Not handling this packet\n"); + return -EINVAL; + } + + /* Adjust the offset for the user buffer and post in the rq */ + + if (pkt_type == BNXT_RE_ROCEV2_IPV4_PACKET) + offset = 20; + + /* + * QP1 loopback packet has 4 bytes of internal header before + * ether header. Skip these four bytes. + */ + if (bnxt_re_is_loopback_packet(rdev, rq_hdr_buf)) + skip_bytes = 4; + + if (bnxt_re_is_vlan_in_packet(rdev, rq_hdr_buf, cqe)) + skip_bytes += VLAN_HLEN; + + /* Store this cqe */ + memcpy(&sqp_entry->cqe, cqe, sizeof(struct bnxt_qplib_cqe)); + sqp_entry->qp1_qp = gsi_qp; + + /* First send SGE . Skip the ether header*/ + s_sge[0].addr = rq_hdr_buf_map + BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE + + skip_bytes; + s_sge[0].lkey = 0xFFFFFFFF; + s_sge[0].length = offset ? BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV4 : + BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6; + + /* Second Send SGE */ + s_sge[1].addr = s_sge[0].addr + s_sge[0].length + + BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE; + if (pkt_type != BNXT_RE_ROCE_V1_PACKET) + s_sge[1].addr += 8; + s_sge[1].lkey = 0xFFFFFFFF; + s_sge[1].length = 256; + + /* First recv SGE */ + r_sge[0].addr = shrq_hdr_buf_map; + r_sge[0].lkey = 0xFFFFFFFF; + r_sge[0].length = 40; + + r_sge[1].addr = sqp_entry->sge.addr + offset; + r_sge[1].lkey = sqp_entry->sge.lkey; + r_sge[1].length = BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6 + 256 - offset; + + /* Create receive work request */ + rwr.num_sge = 2; + rwr.sg_list = r_sge; + rwr.wr_id = tbl_idx; + rwr.next = NULL; + + rc = bnxt_re_post_recv_shadow_qp(rdev, gsi_sqp, &rwr); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to post Rx buffers to shadow QP\n"); + return -ENOMEM; + } + + swr->num_sge = 2; + swr->sg_list = s_sge; + swr->wr_id = tbl_idx; + swr->opcode = IB_WR_SEND; + swr->next = NULL; + + gsi_sah = rdev->gsi_ctx.gsi_sah; + udwr.ah = &gsi_sah->ibah; + udwr.remote_qpn = gsi_sqp->qplib_qp.id; + udwr.remote_qkey = gsi_sqp->qplib_qp.qkey; + /* post data received in the send queue */ + rc = bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr); + + return rc; +} + +static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc, + struct bnxt_qplib_cqe *cqe) +{ + wc->opcode = IB_WC_RECV; + wc->status = __rawqp1_to_ib_wc_status(cqe->status); + wc->wc_flags |= IB_WC_GRH; +} + +static void bnxt_re_process_res_rc_wc(struct ib_wc *wc, + struct bnxt_qplib_cqe *cqe) +{ + wc->opcode = IB_WC_RECV; + wc->status = __rc_to_ib_wc_status(cqe->status); + + if (cqe->flags & CQ_RES_RC_FLAGS_IMM) + wc->wc_flags |= IB_WC_WITH_IMM; + if (cqe->flags & CQ_RES_RC_FLAGS_INV) + wc->wc_flags |= IB_WC_WITH_INVALIDATE; + if ((cqe->flags & (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM)) == + (CQ_RES_RC_FLAGS_RDMA | CQ_RES_RC_FLAGS_IMM)) + wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; +} + +/* Returns TRUE if pkt has valid VLAN and if VLAN id is non-zero */ +static bool bnxt_re_is_nonzero_vlanid_pkt(struct bnxt_qplib_cqe *orig_cqe, + u16 *vid, u8 *sl) +{ + u32 metadata; + u16 tpid; + bool ret = false; + metadata = orig_cqe->raweth_qp1_metadata; + if (orig_cqe->raweth_qp1_flags2 & + CQ_RES_RAWETH_QP1_RAWETH_QP1_FLAGS2_META_FORMAT_VLAN) { + tpid = ((metadata & + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_MASK) >> + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_TPID_SFT); + if (tpid == ETH_P_8021Q) { + *vid = metadata & + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_VID_MASK; + *sl = (metadata & + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_MASK) >> + CQ_RES_RAWETH_QP1_RAWETH_QP1_METADATA_PRI_SFT; + ret = !!(*vid); + } + } + + return ret; +} + +static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp, + struct ib_wc *wc, + struct bnxt_qplib_cqe *cqe) +{ + u32 tbl_idx; + struct bnxt_re_dev *rdev = gsi_sqp->rdev; + struct bnxt_re_qp *gsi_qp = NULL; + struct bnxt_qplib_cqe *orig_cqe = NULL; + struct bnxt_re_sqp_entries *sqp_entry = NULL; + int nw_type; + u16 vlan_id; + u8 sl; + + tbl_idx = cqe->wr_id; + + sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx]; + gsi_qp = sqp_entry->qp1_qp; + orig_cqe = &sqp_entry->cqe; + + wc->wr_id = sqp_entry->wrid; + wc->byte_len = orig_cqe->length; + wc->qp = &gsi_qp->ib_qp; + + wc->ex.imm_data = orig_cqe->immdata; + wc->src_qp = orig_cqe->src_qp; + memcpy(wc->smac, orig_cqe->smac, ETH_ALEN); + if (bnxt_re_is_nonzero_vlanid_pkt(orig_cqe, &vlan_id, &sl)) { + if (bnxt_re_check_if_vlan_valid(rdev, vlan_id)) { + wc->sl = sl; + wc->vlan_id = vlan_id; + wc->wc_flags |= IB_WC_WITH_VLAN; + } + } + wc->port_num = 1; + wc->vendor_err = orig_cqe->status; + + wc->opcode = IB_WC_RECV; + wc->status = __rawqp1_to_ib_wc_status(orig_cqe->status); + wc->wc_flags |= IB_WC_GRH; + + nw_type = bnxt_re_check_packet_type(orig_cqe->raweth_qp1_flags, + orig_cqe->raweth_qp1_flags2); + if(nw_type >= 0) + dev_dbg(rdev_to_dev(rdev), "%s nw_type = %d\n", __func__, nw_type); +} + +static void bnxt_re_process_res_ud_wc(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp, struct ib_wc *wc, + struct bnxt_qplib_cqe *cqe) +{ + u16 vlan_id = 0; + + wc->opcode = IB_WC_RECV; + wc->status = __rc_to_ib_wc_status(cqe->status); + if (cqe->flags & CQ_RES_UD_FLAGS_IMM) + wc->wc_flags |= IB_WC_WITH_IMM; + if (cqe->flags & CQ_RES_RC_FLAGS_INV) + wc->wc_flags |= IB_WC_WITH_INVALIDATE; + /* report only on GSI QP for Thor */ + if (rdev->gsi_ctx.gsi_qp->qplib_qp.id == qp->qplib_qp.id && + rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_UD) { + wc->wc_flags |= IB_WC_GRH; + memcpy(wc->smac, cqe->smac, ETH_ALEN); + wc->wc_flags |= IB_WC_WITH_SMAC; + if (_is_cqe_v2_supported(rdev->dev_attr->dev_cap_flags)) { + if (cqe->flags & CQ_RES_UD_V2_FLAGS_META_FORMAT_MASK) { + if (cqe->cfa_meta & + BNXT_QPLIB_CQE_CFA_META1_VALID) + vlan_id = (cqe->cfa_meta & 0xFFF); + } + } else if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) { + vlan_id = (cqe->cfa_meta & 0xFFF); + } + /* Mark only if vlan_id is non zero */ + if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) { + wc->vlan_id = vlan_id; + wc->wc_flags |= IB_WC_WITH_VLAN; + } + } +} + +static int bnxt_re_legacy_send_phantom_wqe(struct bnxt_re_qp *qp) +{ + struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp; + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&qp->sq_lock, flags); + + rc = bnxt_re_legacy_bind_fence_mw(lib_qp); + if (!rc) { + lib_qp->sq.phantom_wqe_cnt++; + dev_dbg(&lib_qp->sq.hwq.pdev->dev, + "qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n", + lib_qp->id, lib_qp->sq.hwq.prod, + HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq), + lib_qp->sq.phantom_wqe_cnt); + } + + spin_unlock_irqrestore(&qp->sq_lock, flags); + return rc; +} + +int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc) +{ + struct bnxt_re_cq *cq = to_bnxt_re(ib_cq, struct bnxt_re_cq, ibcq); + struct bnxt_re_dev *rdev = cq->rdev; + struct bnxt_re_qp *qp; + struct bnxt_qplib_cqe *cqe; + int i, ncqe, budget, init_budget; + struct bnxt_qplib_q *sq; + struct bnxt_qplib_qp *lib_qp; + u32 tbl_idx; + struct bnxt_re_sqp_entries *sqp_entry = NULL; + unsigned long flags; + u8 gsi_mode; + + /* + * DB recovery CQ; only process the door bell pacing alert from + * the user lib + */ + if (cq->is_dbr_soft_cq) { + bnxt_re_pacing_alert(rdev); + return 0; + } + + /* User CQ; the only processing we do is to + * complete any pending CQ resize operation. + */ + if (cq->umem) { + if (cq->resize_umem) + bnxt_re_resize_cq_complete(cq); + return 0; + } + + spin_lock_irqsave(&cq->cq_lock, flags); + + budget = min_t(u32, num_entries, cq->max_cql); + init_budget = budget; + if (!cq->cql) { + dev_err(rdev_to_dev(rdev), "POLL CQ no CQL to use\n"); + goto exit; + } + cqe = &cq->cql[0]; + gsi_mode = rdev->gsi_ctx.gsi_qp_mode; + while (budget) { + lib_qp = NULL; + ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp); + if (lib_qp) { + sq = &lib_qp->sq; + if (sq->legacy_send_phantom == true) { + qp = container_of(lib_qp, struct bnxt_re_qp, qplib_qp); + if (bnxt_re_legacy_send_phantom_wqe(qp) == -ENOMEM) + dev_err(rdev_to_dev(rdev), + "Phantom failed! Scheduled to send again\n"); + else + sq->legacy_send_phantom = false; + } + } + if (ncqe < budget) + ncqe += bnxt_qplib_process_flush_list(&cq->qplib_cq, + cqe + ncqe, + budget - ncqe); + + if (!ncqe) + break; + + for (i = 0; i < ncqe; i++, cqe++) { + /* Transcribe each qplib_wqe back to ib_wc */ + memset(wc, 0, sizeof(*wc)); + + wc->wr_id = cqe->wr_id; + wc->byte_len = cqe->length; + qp = to_bnxt_re((struct bnxt_qplib_qp *)cqe->qp_handle, + struct bnxt_re_qp, qplib_qp); + if (!qp) { + dev_err(rdev_to_dev(rdev), + "POLL CQ bad QP handle\n"); + continue; + } + wc->qp = &qp->ib_qp; + wc->ex.imm_data = cqe->immdata; + wc->src_qp = cqe->src_qp; + memcpy(wc->smac, cqe->smac, ETH_ALEN); + wc->port_num = 1; + wc->vendor_err = cqe->status; + + switch(cqe->opcode) { + case CQ_BASE_CQE_TYPE_REQ: + if (gsi_mode == BNXT_RE_GSI_MODE_ALL && + qp->qplib_qp.id == + rdev->gsi_ctx.gsi_sqp->qplib_qp.id) { + /* Handle this completion with + * the stored completion */ + dev_dbg(rdev_to_dev(rdev), + "Skipping this UD Send CQ\n"); + memset(wc, 0, sizeof(*wc)); + continue; + } + bnxt_re_process_req_wc(wc, cqe); + break; + case CQ_BASE_CQE_TYPE_RES_RAWETH_QP1: + if (gsi_mode == BNXT_RE_GSI_MODE_ALL) { + if (!cqe->status) { + int rc = 0; + rc = bnxt_re_process_raw_qp_packet_receive(qp, cqe); + if (!rc) { + memset(wc, 0, + sizeof(*wc)); + continue; + } + cqe->status = -1; + } + /* Errors need not be looped back. + * But change the wr_id to the one + * stored in the table + */ + tbl_idx = cqe->wr_id; + sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx]; + wc->wr_id = sqp_entry->wrid; + } + + bnxt_re_process_res_rawqp1_wc(wc, cqe); + break; + case CQ_BASE_CQE_TYPE_RES_RC: + bnxt_re_process_res_rc_wc(wc, cqe); + break; + case CQ_BASE_CQE_TYPE_RES_UD: + if (gsi_mode == BNXT_RE_GSI_MODE_ALL && + qp->qplib_qp.id == + rdev->gsi_ctx.gsi_sqp->qplib_qp.id) { + /* Handle this completion with + * the stored completion + */ + dev_dbg(rdev_to_dev(rdev), + "Handling the UD receive CQ\n"); + if (cqe->status) { + /* TODO handle this completion as a failure in + * loopback porocedure + */ + continue; + } else { + bnxt_re_process_res_shadow_qp_wc(qp, wc, cqe); + break; + } + } + bnxt_re_process_res_ud_wc(rdev, qp, wc, cqe); + break; + default: + dev_err(rdev_to_dev(cq->rdev), + "POLL CQ type 0x%x not handled, skip!\n", + cqe->opcode); + continue; + } + wc++; + budget--; + } + } +exit: + spin_unlock_irqrestore(&cq->cq_lock, flags); + return init_budget - budget; +} + +int bnxt_re_req_notify_cq(struct ib_cq *ib_cq, + enum ib_cq_notify_flags ib_cqn_flags) +{ + struct bnxt_re_cq *cq = to_bnxt_re(ib_cq, struct bnxt_re_cq, ibcq); + int type = 0, rc = 0; + unsigned long flags; + + spin_lock_irqsave(&cq->cq_lock, flags); + /* Trigger on the very next completion */ + if (ib_cqn_flags & IB_CQ_NEXT_COMP) + type = DBC_DBC_TYPE_CQ_ARMALL; + /* Trigger on the next solicited completion */ + else if (ib_cqn_flags & IB_CQ_SOLICITED) + type = DBC_DBC_TYPE_CQ_ARMSE; + + bnxt_qplib_req_notify_cq(&cq->qplib_cq, type); + + /* Poll to see if there are missed events */ + if ((ib_cqn_flags & IB_CQ_REPORT_MISSED_EVENTS) && + !(bnxt_qplib_is_cq_empty(&cq->qplib_cq))) + rc = 1; + + spin_unlock_irqrestore(&cq->cq_lock, flags); + + return rc; +} + +/* Memory Regions */ +struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags) +{ + struct bnxt_qplib_mrinfo mrinfo; + struct bnxt_re_dev *rdev; + struct bnxt_re_mr *mr; + struct bnxt_re_pd *pd; + u32 max_mr_count; + u64 pbl = 0; + int rc; + + memset(&mrinfo, 0, sizeof(mrinfo)); + pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + rdev = pd->rdev; + + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) { + dev_err(rdev_to_dev(rdev), + "Allocate memory for DMA MR failed!\n"); + return ERR_PTR(-ENOMEM); + } + mr->rdev = rdev; + mr->qplib_mr.pd = &pd->qplib_pd; + mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags); + mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR; + + /* Allocate and register 0 as the address */ + rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr); + if (rc) { + dev_err(rdev_to_dev(rdev), "Allocate DMA MR failed!\n"); + goto fail; + } + mr->qplib_mr.total_size = -1; /* Infinite length */ + mrinfo.ptes = &pbl; + mrinfo.sg.npages = 0; + mrinfo.sg.pgsize = PAGE_SIZE; + mrinfo.sg.pgshft = PAGE_SHIFT; + mrinfo.sg.pgsize = PAGE_SIZE; + mrinfo.mrw = &mr->qplib_mr; + mrinfo.is_dma = true; + rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mrinfo, false); + if (rc) { + dev_err(rdev_to_dev(rdev), "Register DMA MR failed!\n"); + goto fail_mr; + } + mr->ib_mr.lkey = mr->qplib_mr.lkey; + if (mr_access_flags & (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ | + IB_ACCESS_REMOTE_ATOMIC)) + mr->ib_mr.rkey = mr->ib_mr.lkey; + atomic_inc(&rdev->stats.rsors.mr_count); + max_mr_count = atomic_read(&rdev->stats.rsors.mr_count); + if (max_mr_count > atomic_read(&rdev->stats.rsors.max_mr_count)) + atomic_set(&rdev->stats.rsors.max_mr_count, max_mr_count); + + return &mr->ib_mr; + +fail_mr: + bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); +fail: + kfree(mr); + return ERR_PTR(rc); +} + +int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata) +{ + struct bnxt_re_mr *mr = to_bnxt_re(ib_mr, struct bnxt_re_mr, ib_mr); + struct bnxt_re_dev *rdev = mr->rdev; + int rc = 0; + + rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); + if (rc) + dev_err(rdev_to_dev(rdev), "Dereg MR failed (%d): rc - %#x\n", + mr->qplib_mr.lkey, rc); + + if (mr->pages) { + bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res, + &mr->qplib_frpl); + kfree(mr->pages); + mr->npages = 0; + mr->pages = NULL; + } + if (!IS_ERR(mr->ib_umem) && mr->ib_umem) { + mr->is_invalcb_active = false; + bnxt_re_peer_mem_release(mr->ib_umem); + } + kfree(mr); + atomic_dec(&rdev->stats.rsors.mr_count); + return 0; +} + +static int bnxt_re_set_page(struct ib_mr *ib_mr, u64 addr) +{ + struct bnxt_re_mr *mr = to_bnxt_re(ib_mr, struct bnxt_re_mr, ib_mr); + + if (unlikely(mr->npages == mr->qplib_frpl.max_pg_ptrs)) + return -ENOMEM; + + mr->pages[mr->npages++] = addr; + dev_dbg(NULL, "%s: ibdev %p Set MR pages[%d] = 0x%lx\n", + ROCE_DRV_MODULE_NAME, ib_mr->device, mr->npages - 1, + mr->pages[mr->npages - 1]); + return 0; +} + +int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, + int sg_nents, unsigned int *sg_offset) +{ + struct bnxt_re_mr *mr = to_bnxt_re(ib_mr, struct bnxt_re_mr, ib_mr); + + mr->npages = 0; + return ib_sg_to_pages(ib_mr, sg, sg_nents, + sg_offset, bnxt_re_set_page); +} + +struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type, + u32 max_num_sg, struct ib_udata *udata) +{ + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_mr *mr; + u32 max_mr_count; + int rc; + + dev_dbg(rdev_to_dev(rdev), "Alloc MR\n"); + if (type != IB_MR_TYPE_MEM_REG) { + dev_dbg(rdev_to_dev(rdev), "MR type 0x%x not supported\n", type); + return ERR_PTR(-EINVAL); + } + if (max_num_sg > MAX_PBL_LVL_1_PGS) { + dev_dbg(rdev_to_dev(rdev), "Max SG exceeded\n"); + return ERR_PTR(-EINVAL); + } + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) { + dev_err(rdev_to_dev(rdev), "Allocate MR mem failed!\n"); + return ERR_PTR(-ENOMEM); + } + mr->rdev = rdev; + mr->qplib_mr.pd = &pd->qplib_pd; + mr->qplib_mr.flags = BNXT_QPLIB_FR_PMR; + mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR; + + rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr); + if (rc) { + dev_err(rdev_to_dev(rdev), "Allocate MR failed!\n"); + goto fail; + } + mr->ib_mr.lkey = mr->qplib_mr.lkey; + mr->ib_mr.rkey = mr->ib_mr.lkey; + mr->pages = kzalloc(sizeof(u64) * max_num_sg, GFP_KERNEL); + if (!mr->pages) { + dev_err(rdev_to_dev(rdev), + "Allocate MR page list mem failed!\n"); + rc = -ENOMEM; + goto fail_mr; + } + rc = bnxt_qplib_alloc_fast_reg_page_list(&rdev->qplib_res, + &mr->qplib_frpl, max_num_sg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Allocate HW Fast reg page list failed!\n"); + goto free_page; + } + dev_dbg(rdev_to_dev(rdev), "Alloc MR pages = 0x%p\n", mr->pages); + + atomic_inc(&rdev->stats.rsors.mr_count); + max_mr_count = atomic_read(&rdev->stats.rsors.mr_count); + if (max_mr_count > atomic_read(&rdev->stats.rsors.max_mr_count)) + atomic_set(&rdev->stats.rsors.max_mr_count, max_mr_count); + return &mr->ib_mr; + +free_page: + kfree(mr->pages); +fail_mr: + bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); +fail: + kfree(mr); + return ERR_PTR(rc); +} + +/* Memory Windows */ +struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type, + struct ib_udata *udata) +{ + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_re_mw *mw; + u32 max_mw_count; + int rc; + + mw = kzalloc(sizeof(*mw), GFP_KERNEL); + if (!mw) { + dev_err(rdev_to_dev(rdev), "Allocate MW failed!\n"); + rc = -ENOMEM; + goto exit; + } + mw->rdev = rdev; + mw->qplib_mw.pd = &pd->qplib_pd; + + mw->qplib_mw.type = (type == IB_MW_TYPE_1 ? + CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 : + CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B); + rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw); + if (rc) { + dev_err(rdev_to_dev(rdev), "Allocate MW failed!\n"); + goto fail; + } + mw->ib_mw.rkey = mw->qplib_mw.rkey; + atomic_inc(&rdev->stats.rsors.mw_count); + max_mw_count = atomic_read(&rdev->stats.rsors.mw_count); + if (max_mw_count > atomic_read(&rdev->stats.rsors.max_mw_count)) + atomic_set(&rdev->stats.rsors.max_mw_count, max_mw_count); + + return &mw->ib_mw; +fail: + kfree(mw); +exit: + return ERR_PTR(rc); +} + +int bnxt_re_dealloc_mw(struct ib_mw *ib_mw) +{ + struct bnxt_re_mw *mw = to_bnxt_re(ib_mw, struct bnxt_re_mw, ib_mw); + struct bnxt_re_dev *rdev = mw->rdev; + int rc; + + rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw); + if (rc) { + dev_err(rdev_to_dev(rdev), "Free MW failed: %#x\n", rc); + return rc; + } + + kfree(mw); + atomic_dec(&rdev->stats.rsors.mw_count); + return rc; +} + +static int bnxt_re_page_size_ok(int page_shift) +{ + switch (page_shift) { + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_4K: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_8K: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_64K: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_2M: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_256K: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_1M: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_4M: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_256MB: + case CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_1G: + return 1; + default: + return 0; + } +} + +static int bnxt_re_get_page_shift(struct ib_umem *umem, + u64 va, u64 st, u64 cmask) +{ + int pgshft; + + pgshft = ilog2(umem->page_size); + + return pgshft; +} + +static int bnxt_re_get_num_pages(struct ib_umem *umem, u64 start, u64 length, int page_shift) +{ + int npages = 0; + + if (page_shift == PAGE_SHIFT) { + npages = ib_umem_num_pages_compat(umem); + } else { + npages = ALIGN(length, BIT(page_shift)) / BIT(page_shift); + if (start % BIT(page_shift)) + npages++; + } + return npages; +} + +/* uverbs */ +struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length, + u64 virt_addr, int mr_access_flags, + struct ib_udata *udata) +{ + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + struct bnxt_re_dev *rdev = pd->rdev; + struct bnxt_qplib_mrinfo mrinfo; + int umem_pgs, page_shift, rc; + struct bnxt_re_mr *mr; + struct ib_umem *umem; + u32 max_mr_count; + int npages; + + dev_dbg(rdev_to_dev(rdev), "Reg user MR\n"); + + if (bnxt_re_get_total_mr_mw_count(rdev) >= rdev->dev_attr->max_mr) + return ERR_PTR(-ENOMEM); + + if (rdev->mod_exit) { + dev_dbg(rdev_to_dev(rdev), "%s(): in mod_exit, just return!\n", __func__); + return ERR_PTR(-EIO); + } + memset(&mrinfo, 0, sizeof(mrinfo)); + if (length > BNXT_RE_MAX_MR_SIZE) { + dev_err(rdev_to_dev(rdev), "Requested MR Size: %lu " + "> Max supported: %ld\n", length, BNXT_RE_MAX_MR_SIZE); + return ERR_PTR(-ENOMEM); + } + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) { + dev_err(rdev_to_dev(rdev), "Allocate MR failed!\n"); + return ERR_PTR (-ENOMEM); + } + mr->rdev = rdev; + mr->qplib_mr.pd = &pd->qplib_pd; + mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags); + mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR; + + if (!_is_alloc_mr_unified(rdev->qplib_res.dattr)) { + rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr); + if (rc) { + dev_err(rdev_to_dev(rdev), "Alloc MR failed!\n"); + goto fail; + } + /* The fixed portion of the rkey is the same as the lkey */ + mr->ib_mr.rkey = mr->qplib_mr.rkey; + } + + umem = ib_umem_get_flags_compat(rdev, ib_pd->uobject->context, + udata, start, length, + mr_access_flags, 0); + if (IS_ERR(umem)) { + rc = PTR_ERR(umem); + dev_err(rdev_to_dev(rdev), "%s: ib_umem_get failed! rc = %d\n", + __func__, rc); + goto free_mr; + } + mr->ib_umem = umem; + + mr->qplib_mr.va = virt_addr; + umem_pgs = ib_umem_num_pages_compat(umem); + if (!umem_pgs) { + dev_err(rdev_to_dev(rdev), "umem is invalid!\n"); + rc = -EINVAL; + goto free_umem; + } + mr->qplib_mr.total_size = length; + page_shift = bnxt_re_get_page_shift(umem, virt_addr, start, + rdev->dev_attr->page_size_cap); + if (!bnxt_re_page_size_ok(page_shift)) { + dev_err(rdev_to_dev(rdev), "umem page size unsupported!\n"); + rc = -EFAULT; + goto free_umem; + } + npages = bnxt_re_get_num_pages(umem, start, length, page_shift); + + /* Map umem buf ptrs to the PBL */ + mrinfo.sg.npages = npages; + mrinfo.sg.sghead = get_ib_umem_sgl(umem, &mrinfo.sg.nmap); + mrinfo.sg.pgshft = page_shift; + mrinfo.sg.pgsize = BIT(page_shift); + + mrinfo.mrw = &mr->qplib_mr; + + rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mrinfo, false); + if (rc) { + dev_err(rdev_to_dev(rdev), "Reg user MR failed!\n"); + goto free_umem; + } + + mr->ib_mr.lkey = mr->ib_mr.rkey = mr->qplib_mr.lkey; + atomic_inc(&rdev->stats.rsors.mr_count); + max_mr_count = atomic_read(&rdev->stats.rsors.mr_count); + if (max_mr_count > atomic_read(&rdev->stats.rsors.max_mr_count)) + atomic_set(&rdev->stats.rsors.max_mr_count, max_mr_count); + + return &mr->ib_mr; + +free_umem: + bnxt_re_peer_mem_release(mr->ib_umem); +free_mr: + if (!_is_alloc_mr_unified(rdev->qplib_res.dattr)) + bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr); +fail: + kfree(mr); + return ERR_PTR(rc); +} + +int +bnxt_re_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, u64 length, + u64 virt_addr, int mr_access_flags, + struct ib_pd *ib_pd, struct ib_udata *udata) +{ + struct bnxt_re_mr *mr = to_bnxt_re(ib_mr, struct bnxt_re_mr, ib_mr); + struct bnxt_re_pd *pd = to_bnxt_re(ib_pd, struct bnxt_re_pd, ibpd); + int umem_pgs = 0, page_shift = PAGE_SHIFT, rc; + struct bnxt_re_dev *rdev = mr->rdev; + struct bnxt_qplib_mrinfo mrinfo; + struct ib_umem *umem; + u32 npages; + + /* TODO: Must decipher what to modify based on the flags */ + memset(&mrinfo, 0, sizeof(mrinfo)); + if (flags & IB_MR_REREG_TRANS) { + umem = ib_umem_get_flags_compat(rdev, ib_pd->uobject->context, + udata, start, length, + mr_access_flags, 0); + if (IS_ERR(umem)) { + rc = PTR_ERR(umem); + dev_err(rdev_to_dev(rdev), + "%s: ib_umem_get failed! ret = %d\n", + __func__, rc); + goto fail; + } + mr->ib_umem = umem; + + mr->qplib_mr.va = virt_addr; + umem_pgs = ib_umem_num_pages_compat(umem); + if (!umem_pgs) { + dev_err(rdev_to_dev(rdev), "umem is invalid!\n"); + rc = -EINVAL; + goto fail_free_umem; + } + mr->qplib_mr.total_size = length; + page_shift = bnxt_re_get_page_shift(umem, virt_addr, start, + rdev->dev_attr->page_size_cap); + if (!bnxt_re_page_size_ok(page_shift)) { + dev_err(rdev_to_dev(rdev), + "umem page size unsupported!\n"); + rc = -EFAULT; + goto fail_free_umem; + } + npages = bnxt_re_get_num_pages(umem, start, length, page_shift); + /* Map umem buf ptrs to the PBL */ + mrinfo.sg.npages = npages; + mrinfo.sg.sghead = get_ib_umem_sgl(umem, &mrinfo.sg.nmap); + mrinfo.sg.pgshft = page_shift; + mrinfo.sg.pgsize = BIT(page_shift); + } + + mrinfo.mrw = &mr->qplib_mr; + if (flags & IB_MR_REREG_PD) + mr->qplib_mr.pd = &pd->qplib_pd; + + if (flags & IB_MR_REREG_ACCESS) + mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags); + + rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mrinfo, false); + if (rc) { + dev_err(rdev_to_dev(rdev), "Rereg user MR failed!\n"); + goto fail_free_umem; + } + mr->ib_mr.rkey = mr->qplib_mr.rkey; + + return 0; + +fail_free_umem: + bnxt_re_peer_mem_release(mr->ib_umem); +fail: + return rc; +} + +static int bnxt_re_check_abi_version(struct bnxt_re_dev *rdev) +{ + struct ib_device *ibdev = &rdev->ibdev; + u32 uverbs_abi_ver; + + uverbs_abi_ver = GET_UVERBS_ABI_VERSION(ibdev); + dev_dbg(rdev_to_dev(rdev), "ABI version requested %d\n", + uverbs_abi_ver); + if (uverbs_abi_ver != BNXT_RE_ABI_VERSION) { + dev_dbg(rdev_to_dev(rdev), " is different from the device %d \n", + BNXT_RE_ABI_VERSION); + return -EPERM; + } + return 0; +} + +int bnxt_re_alloc_ucontext(struct ib_ucontext *uctx_in, + struct ib_udata *udata) +{ + struct ib_ucontext *ctx = uctx_in; + struct ib_device *ibdev = ctx->device; + struct bnxt_re_ucontext *uctx = + container_of(ctx, struct bnxt_re_ucontext, ibucontext); + + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr; + struct bnxt_re_uctx_resp resp = {}; + struct bnxt_re_uctx_req ureq = {}; + struct bnxt_qplib_chip_ctx *cctx; + u32 chip_met_rev_num; + bool genp5 = false; + int rc; + + cctx = rdev->chip_ctx; + rc = bnxt_re_check_abi_version(rdev); + if (rc) + goto fail; + + uctx->rdev = rdev; + uctx->shpg = (void *)__get_free_page(GFP_KERNEL); + if (!uctx->shpg) { + dev_err(rdev_to_dev(rdev), "shared memory allocation failed!\n"); + rc = -ENOMEM; + goto fail; + } + spin_lock_init(&uctx->sh_lock); + if (BNXT_RE_ABI_VERSION >= 4) { + chip_met_rev_num = cctx->chip_num; + chip_met_rev_num |= ((u32)cctx->chip_rev & 0xFF) << + BNXT_RE_CHIP_ID0_CHIP_REV_SFT; + chip_met_rev_num |= ((u32)cctx->chip_metal & 0xFF) << + BNXT_RE_CHIP_ID0_CHIP_MET_SFT; + resp.chip_id0 = chip_met_rev_num; + resp.chip_id1 = 0; /* future extension of chip info */ + } + + if (BNXT_RE_ABI_VERSION != 4) { + /*Temp, Use idr_alloc instead*/ + resp.dev_id = rdev->en_dev->pdev->devfn; + resp.max_qp = rdev->qplib_res.hctx->qp_ctx.max; + } + + genp5 = _is_chip_gen_p5_p7(cctx); + if (BNXT_RE_ABI_VERSION > 5) { + resp.modes = genp5 ? cctx->modes.wqe_mode : 0; + if (rdev->dev_attr && BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) + resp.comp_mask = BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED; + } + + resp.pg_size = PAGE_SIZE; + resp.cqe_sz = sizeof(struct cq_base); + resp.max_cqd = dev_attr->max_cq_wqes; + if (genp5 && cctx->modes.db_push) { + resp.comp_mask |= BNXT_RE_COMP_MASK_UCNTX_WC_DPI_ENABLED; + if (_is_chip_p7(cctx) && + !(dev_attr->dev_cap_flags & + CREQ_QUERY_FUNC_RESP_SB_PINGPONG_PUSH_MODE)) + resp.comp_mask &= + ~BNXT_RE_COMP_MASK_UCNTX_WC_DPI_ENABLED; + } + + resp.comp_mask |= BNXT_RE_COMP_MASK_UCNTX_MQP_EX_SUPPORTED; + + if (rdev->dbr_pacing) + resp.comp_mask |= BNXT_RE_COMP_MASK_UCNTX_DBR_PACING_ENABLED; + + if (rdev->dbr_drop_recov && rdev->user_dbr_drop_recov) + resp.comp_mask |= BNXT_RE_COMP_MASK_UCNTX_DBR_RECOVERY_ENABLED; + + if (udata->inlen >= sizeof(ureq)) { + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + goto cfail; + if (bnxt_re_init_pow2_flag(&ureq, &resp)) + dev_warn(rdev_to_dev(rdev), + "Enabled roundup logic. Library bug?\n"); + if (bnxt_re_init_rsvd_wqe_flag(&ureq, &resp, genp5)) + dev_warn(rdev_to_dev(rdev), + "Rsvd wqe in use! Try the updated library.\n"); + } else { + dev_warn(rdev_to_dev(rdev), + "Enabled roundup logic. Update the library!\n"); + resp.comp_mask &= ~BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED; + + dev_warn(rdev_to_dev(rdev), + "Rsvd wqe in use. Update the library!\n"); + resp.comp_mask &= ~BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED; + } + + uctx->cmask = (uint64_t)resp.comp_mask; + rc = bnxt_re_copy_to_udata(rdev, &resp, + min(udata->outlen, sizeof(resp)), + udata); + if (rc) + goto cfail; + + INIT_LIST_HEAD(&uctx->cq_list); + mutex_init(&uctx->cq_lock); + + return 0; +cfail: + free_page((u64)uctx->shpg); + uctx->shpg = NULL; +fail: + return rc; +} + +void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx) +{ + struct bnxt_re_ucontext *uctx = to_bnxt_re(ib_uctx, + struct bnxt_re_ucontext, + ibucontext); + struct bnxt_re_dev *rdev = uctx->rdev; + int rc = 0; + + if (uctx->shpg) + free_page((u64)uctx->shpg); + + if (uctx->dpi.dbr) { + /* Free DPI only if this is the first PD allocated by the + * application and mark the context dpi as NULL + */ + if (_is_chip_gen_p5_p7(rdev->chip_ctx) && uctx->wcdpi.dbr) { + rc = bnxt_qplib_dealloc_dpi(&rdev->qplib_res, + &uctx->wcdpi); + if (rc) + dev_err(rdev_to_dev(rdev), + "dealloc push dp failed\n"); + uctx->wcdpi.dbr = NULL; + } + + rc = bnxt_qplib_dealloc_dpi(&rdev->qplib_res, + &uctx->dpi); + if (rc) + dev_err(rdev_to_dev(rdev), "Deallocte HW DPI failed!\n"); + /* Don't fail, continue*/ + uctx->dpi.dbr = NULL; + } + return; +} + +static struct bnxt_re_cq *is_bnxt_re_cq_page(struct bnxt_re_ucontext *uctx, + u64 pg_off) +{ + struct bnxt_re_cq *cq = NULL, *tmp_cq; + + if (!_is_chip_p7(uctx->rdev->chip_ctx)) + return NULL; + + mutex_lock(&uctx->cq_lock); + list_for_each_entry(tmp_cq, &uctx->cq_list, cq_list) { + if (((u64)tmp_cq->uctx_cq_page >> PAGE_SHIFT) == pg_off) { + cq = tmp_cq; + break; + } + } + mutex_unlock(&uctx->cq_lock); + return cq; +} + +/* Helper function to mmap the virtual memory from user app */ +int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma) +{ + struct bnxt_re_ucontext *uctx = to_bnxt_re(ib_uctx, + struct bnxt_re_ucontext, + ibucontext); + struct bnxt_re_dev *rdev = uctx->rdev; + struct bnxt_re_cq *cq = NULL; + int rc = 0; + u64 pfn; + + switch (vma->vm_pgoff) { + case BNXT_RE_MAP_SH_PAGE: + pfn = vtophys(uctx->shpg) >> PAGE_SHIFT; + return rdma_user_mmap_io(&uctx->ibucontext, vma, pfn, PAGE_SIZE, vma->vm_page_prot, NULL); + dev_dbg(rdev_to_dev(rdev), "%s:%d uctx->shpg 0x%lx, vtophys(uctx->shpg) 0x%lx, pfn = 0x%lx \n", + __func__, __LINE__, (u64) uctx->shpg, vtophys(uctx->shpg), pfn); + if (rc) { + dev_err(rdev_to_dev(rdev), "Shared page mapping failed!\n"); + rc = -EAGAIN; + } + return rc; + case BNXT_RE_MAP_WC: + vma->vm_page_prot = + pgprot_writecombine(vma->vm_page_prot); + pfn = (uctx->wcdpi.umdbr >> PAGE_SHIFT); + if (!pfn) + return -EFAULT; + break; + case BNXT_RE_DBR_PAGE: + /* Driver doesn't expect write access request */ + if (vma->vm_flags & VM_WRITE) + return -EFAULT; + + pfn = vtophys(rdev->dbr_page) >> PAGE_SHIFT; + if (!pfn) + return -EFAULT; + break; + case BNXT_RE_MAP_DB_RECOVERY_PAGE: + pfn = vtophys(uctx->dbr_recov_cq_page) >> PAGE_SHIFT; + if (!pfn) + return -EFAULT; + break; + default: + cq = is_bnxt_re_cq_page(uctx, vma->vm_pgoff); + if (cq) { + pfn = vtophys((void *)cq->uctx_cq_page) >> PAGE_SHIFT; + rc = rdma_user_mmap_io(&uctx->ibucontext, vma, pfn, PAGE_SIZE, vma->vm_page_prot, NULL); + if (rc) { + dev_err(rdev_to_dev(rdev), + "CQ page mapping failed!\n"); + rc = -EAGAIN; + } + goto out; + } else { + vma->vm_page_prot = + pgprot_noncached(vma->vm_page_prot); + pfn = vma->vm_pgoff; + } + break; + } + + rc = rdma_user_mmap_io(&uctx->ibucontext, vma, pfn, PAGE_SIZE, vma->vm_page_prot, NULL); + if (rc) { + dev_err(rdev_to_dev(rdev), "DPI mapping failed!\n"); + return -EAGAIN; + } + rc = __bnxt_re_set_vma_data(uctx, vma); +out: + return rc; +} + +int bnxt_re_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + const struct ib_wc *wc, const struct ib_grh *grh, + const struct ib_mad_hdr *in_mad, size_t in_mad_size, + struct ib_mad_hdr *out_mad, size_t *out_mad_size, + u16 *out_mad_pkey_index) +{ + return IB_MAD_RESULT_SUCCESS; +} + +void bnxt_re_disassociate_ucntx(struct ib_ucontext *ib_uctx) +{ +} diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.h b/sys/dev/bnxt/bnxt_re/ib_verbs.h new file mode 100644 index 000000000000..cb9f7974e92d --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/ib_verbs.h @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: IB Verbs interpreter (header) + */ + +#ifndef __BNXT_RE_IB_VERBS_H__ +#define __BNXT_RE_IB_VERBS_H__ + +#include <rdma/ib_addr.h> +#include "bnxt_re-abi.h" +#include "qplib_res.h" +#include "qplib_fp.h" + +struct bnxt_re_dev; + +#define BNXT_RE_ROCE_V2_UDP_SPORT 0x8CD1 +#define BNXT_RE_QP_RANDOM_QKEY 0x81818181 + +#ifndef IB_MTU_8192 +#define IB_MTU_8192 8192 +#endif + +#ifndef SPEED_1000 +#define SPEED_1000 1000 +#endif + +#ifndef SPEED_10000 +#define SPEED_10000 10000 +#endif + +#ifndef SPEED_20000 +#define SPEED_20000 20000 +#endif + +#ifndef SPEED_25000 +#define SPEED_25000 25000 +#endif + +#ifndef SPEED_40000 +#define SPEED_40000 40000 +#endif + +#ifndef SPEED_50000 +#define SPEED_50000 50000 +#endif + +#ifndef SPEED_100000 +#define SPEED_100000 100000 +#endif + +#ifndef SPEED_200000 +#define SPEED_200000 200000 +#endif + +#ifndef IB_SPEED_HDR +#define IB_SPEED_HDR 64 +#endif + +#define RDMA_NETWORK_IPV4 1 +#define RDMA_NETWORK_IPV6 2 + +#define ROCE_DMAC(x) (x)->dmac + +#define dma_rmb() rmb() + +#define compat_ib_alloc_device(size) ib_alloc_device(size); + +#define rdev_from_cq_in(cq_in) to_bnxt_re_dev(cq_in->device, ibdev) + +#define GET_UVERBS_ABI_VERSION(ibdev) (ibdev->uverbs_abi_ver) + +#define CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_PG_256MB 0x1cUL + +#define IB_POLL_UNBOUND_WORKQUEUE IB_POLL_WORKQUEUE + +#define BNXT_RE_LEGACY_FENCE_BYTES 64 +#define BNXT_RE_LEGACY_FENCE_PBL_SIZE DIV_ROUND_UP(BNXT_RE_LEGACY_FENCE_BYTES, PAGE_SIZE) + + +static inline struct +bnxt_re_cq *__get_cq_from_cq_in(struct ib_cq *cq_in, + struct bnxt_re_dev *rdev); +static inline struct +bnxt_re_qp *__get_qp_from_qp_in(struct ib_pd *qp_in, + struct bnxt_re_dev *rdev); + +static inline bool +bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev, u16 vlan_id); + +#define bnxt_re_compat_qfwstr(void) \ + bnxt_re_query_fw_str(struct ib_device *ibdev, \ + char *str, size_t str_len) + +static inline +struct scatterlist *get_ib_umem_sgl(struct ib_umem *umem, u32 *nmap); + +struct bnxt_re_gid_ctx { + u32 idx; + u32 refcnt; +}; + +struct bnxt_re_legacy_fence_data { + u32 size; + void *va; + dma_addr_t dma_addr; + struct bnxt_re_mr *mr; + struct ib_mw *mw; + struct bnxt_qplib_swqe bind_wqe; + u32 bind_rkey; +}; + +struct bnxt_re_pd { + struct ib_pd ibpd; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_pd qplib_pd; + struct bnxt_re_legacy_fence_data fence; +}; + +struct bnxt_re_ah { + struct ib_ah ibah; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_ah qplib_ah; +}; + +struct bnxt_re_srq { + struct ib_srq ibsrq; + struct bnxt_re_dev *rdev; + u32 srq_limit; + struct bnxt_qplib_srq qplib_srq; + struct ib_umem *umem; + spinlock_t lock; +}; + +union ip_addr { + u32 ipv4_addr; + u8 ipv6_addr[16]; +}; + +struct bnxt_re_qp_info_entry { + union ib_gid sgid; + union ib_gid dgid; + union ip_addr s_ip; + union ip_addr d_ip; + u16 s_port; +#define BNXT_RE_QP_DEST_PORT 4791 + u16 d_port; +}; + +struct bnxt_re_qp { + struct ib_qp ib_qp; + struct list_head list; + struct bnxt_re_dev *rdev; + spinlock_t sq_lock; + spinlock_t rq_lock; + struct bnxt_qplib_qp qplib_qp; + struct ib_umem *sumem; + struct ib_umem *rumem; + /* QP1 */ + u32 send_psn; + struct ib_ud_header qp1_hdr; + struct bnxt_re_cq *scq; + struct bnxt_re_cq *rcq; + struct dentry *qp_info_pdev_dentry; + struct bnxt_re_qp_info_entry qp_info_entry; + void *qp_data; +}; + +struct bnxt_re_cq { + struct ib_cq ibcq; + struct list_head cq_list; + struct bnxt_re_dev *rdev; + struct bnxt_re_ucontext *uctx; + spinlock_t cq_lock; + u16 cq_count; + u16 cq_period; + struct bnxt_qplib_cq qplib_cq; + struct bnxt_qplib_cqe *cql; +#define MAX_CQL_PER_POLL 1024 + u32 max_cql; + struct ib_umem *umem; + struct ib_umem *resize_umem; + struct ib_ucontext *context; + int resize_cqe; + /* list of cq per uctx. Used only for Thor-2 */ + void *uctx_cq_page; + void *dbr_recov_cq_page; + bool is_dbr_soft_cq; +}; + +struct bnxt_re_mr { + struct bnxt_re_dev *rdev; + struct ib_mr ib_mr; + struct ib_umem *ib_umem; + struct bnxt_qplib_mrw qplib_mr; + u32 npages; + u64 *pages; + struct bnxt_qplib_frpl qplib_frpl; + bool is_invalcb_active; +}; + +struct bnxt_re_frpl { + struct bnxt_re_dev *rdev; + struct bnxt_qplib_frpl qplib_frpl; + u64 *page_list; +}; + +struct bnxt_re_mw { + struct bnxt_re_dev *rdev; + struct ib_mw ib_mw; + struct bnxt_qplib_mrw qplib_mw; +}; + +struct bnxt_re_ucontext { + struct ib_ucontext ibucontext; + struct bnxt_re_dev *rdev; + struct list_head cq_list; + struct bnxt_qplib_dpi dpi; + struct bnxt_qplib_dpi wcdpi; + void *shpg; + spinlock_t sh_lock; + uint64_t cmask; + struct mutex cq_lock; /* Protect cq list */ + void *dbr_recov_cq_page; + struct bnxt_re_cq *dbr_recov_cq; +}; + +struct bnxt_re_ah_info { + union ib_gid sgid; + struct ib_gid_attr sgid_attr; + u16 vlan_tag; + u8 nw_type; +}; + +struct ifnet *bnxt_re_get_netdev(struct ib_device *ibdev, + u8 port_num); + +int bnxt_re_query_device(struct ib_device *ibdev, + struct ib_device_attr *ib_attr, + struct ib_udata *udata); +int bnxt_re_modify_device(struct ib_device *ibdev, + int device_modify_mask, + struct ib_device_modify *device_modify); +int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num, + struct ib_port_attr *port_attr); +int bnxt_re_modify_port(struct ib_device *ibdev, u8 port_num, + int port_modify_mask, + struct ib_port_modify *port_modify); +int bnxt_re_get_port_immutable(struct ib_device *ibdev, u8 port_num, + struct ib_port_immutable *immutable); +void bnxt_re_compat_qfwstr(void); +int bnxt_re_query_pkey(struct ib_device *ibdev, u8 port_num, + u16 index, u16 *pkey); +int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num, + unsigned int index, void **context); +int bnxt_re_add_gid(struct ib_device *ibdev, u8 port_num, + unsigned int index, const union ib_gid *gid, + const struct ib_gid_attr *attr, void **context); +int bnxt_re_query_gid(struct ib_device *ibdev, u8 port_num, + int index, union ib_gid *gid); +enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev, + u8 port_num); +int bnxt_re_alloc_pd(struct ib_pd *pd_in, struct ib_udata *udata); +void bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata); + +int bnxt_re_create_ah(struct ib_ah *ah_in, struct ib_ah_attr *attr, + u32 flags, struct ib_udata *udata); + +int bnxt_re_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); +int bnxt_re_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); + +void bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags); +int bnxt_re_create_srq(struct ib_srq *srq_in, + struct ib_srq_init_attr *srq_init_attr, + struct ib_udata *udata); +int bnxt_re_modify_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr, + enum ib_srq_attr_mask srq_attr_mask, + struct ib_udata *udata); +int bnxt_re_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr); +void bnxt_re_destroy_srq(struct ib_srq *ib_srq, + struct ib_udata *udata); +int bnxt_re_post_srq_recv(struct ib_srq *ib_srq, const struct ib_recv_wr *wr, + const struct ib_recv_wr **bad_wr); +struct ib_qp *bnxt_re_create_qp(struct ib_pd *qp_in, + struct ib_qp_init_attr *qp_init_attr, + struct ib_udata *udata); +int bnxt_re_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, + int qp_attr_mask, struct ib_udata *udata); +int bnxt_re_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, + int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); +int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata); +int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr); +int bnxt_re_post_recv(struct ib_qp *ib_qp, const struct ib_recv_wr *wr, + const struct ib_recv_wr **bad_wr); +int bnxt_re_create_cq(struct ib_cq *cq_in, + const struct ib_cq_init_attr *attr, + struct ib_udata *udata); +void bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata); +int bnxt_re_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); +int bnxt_re_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); +int bnxt_re_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc); +int bnxt_re_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags); +struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *pd, int mr_access_flags); +int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, + int sg_nents, unsigned int *sg_offset); +struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type, + u32 max_num_sg, struct ib_udata *udata); +int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata); +struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type, + struct ib_udata *udata); +int bnxt_re_dealloc_mw(struct ib_mw *mw); +struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + u64 virt_addr, int mr_access_flags, + struct ib_udata *udata); +int +bnxt_re_rereg_user_mr(struct ib_mr *mr, int flags, u64 start, u64 length, + u64 virt_addr, int mr_access_flags, struct ib_pd *pd, + struct ib_udata *udata); +int bnxt_re_alloc_ucontext(struct ib_ucontext *uctx_in, + struct ib_udata *udata); +void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx); +int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); +int bnxt_re_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + const struct ib_wc *wc, const struct ib_grh *grh, + const struct ib_mad_hdr *in_mad, size_t in_mad_size, + struct ib_mad_hdr *out_mad, size_t *out_mad_size, + u16 *out_mad_pkey_index); +unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp); +void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags); +void bnxt_re_disassociate_ucntx(struct ib_ucontext *ibcontext); +static inline int __bnxt_re_set_vma_data(void *bnxt_re_uctx, + struct vm_area_struct *vma); +void bnxt_re_update_shadow_ah(struct bnxt_re_dev *rdev); +void bnxt_re_handle_cqn(struct bnxt_qplib_cq *cq); +static inline int +bnxt_re_get_cached_gid(struct ib_device *dev, u8 port_num, int index, + union ib_gid *sgid, struct ib_gid_attr **sgid_attr, + struct ib_global_route *grh, struct ib_ah *ah); +static inline enum rdma_network_type +bnxt_re_gid_to_network_type(struct ib_gid_attr *sgid_attr, + union ib_gid *sgid); +static inline +struct ib_umem *ib_umem_get_compat(struct bnxt_re_dev *rdev, + struct ib_ucontext *ucontext, + struct ib_udata *udata, + unsigned long addr, + size_t size, int access, int dmasync); +static inline +struct ib_umem *ib_umem_get_flags_compat(struct bnxt_re_dev *rdev, + struct ib_ucontext *ucontext, + struct ib_udata *udata, + unsigned long addr, + size_t size, int access, int dmasync); +static inline size_t ib_umem_num_pages_compat(struct ib_umem *umem); +static inline void bnxt_re_peer_mem_release(struct ib_umem *umem); +void bnxt_re_resolve_dmac_task(struct work_struct *work); + +static inline enum ib_qp_type __from_hw_to_ib_qp_type(u8 type) +{ + switch (type) { + case CMDQ_CREATE_QP1_TYPE_GSI: + case CMDQ_CREATE_QP_TYPE_GSI: + return IB_QPT_GSI; + case CMDQ_CREATE_QP_TYPE_RC: + return IB_QPT_RC; + case CMDQ_CREATE_QP_TYPE_UD: + return IB_QPT_UD; + case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE: + return IB_QPT_RAW_ETHERTYPE; + default: + return IB_QPT_MAX; + } +} + +static inline u8 __from_ib_qp_state(enum ib_qp_state state) +{ + switch (state) { + case IB_QPS_RESET: + return CMDQ_MODIFY_QP_NEW_STATE_RESET; + case IB_QPS_INIT: + return CMDQ_MODIFY_QP_NEW_STATE_INIT; + case IB_QPS_RTR: + return CMDQ_MODIFY_QP_NEW_STATE_RTR; + case IB_QPS_RTS: + return CMDQ_MODIFY_QP_NEW_STATE_RTS; + case IB_QPS_SQD: + return CMDQ_MODIFY_QP_NEW_STATE_SQD; + case IB_QPS_SQE: + return CMDQ_MODIFY_QP_NEW_STATE_SQE; + case IB_QPS_ERR: + default: + return CMDQ_MODIFY_QP_NEW_STATE_ERR; + } +} + +static inline u32 __from_ib_mtu(enum ib_mtu mtu) +{ + switch (mtu) { + case IB_MTU_256: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_256; + case IB_MTU_512: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_512; + case IB_MTU_1024: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_1024; + case IB_MTU_2048: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048; + case IB_MTU_4096: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_4096; + default: + return CMDQ_MODIFY_QP_PATH_MTU_MTU_2048; + } +} + +static inline enum ib_mtu __to_ib_mtu(u32 mtu) +{ + switch (mtu & CREQ_QUERY_QP_RESP_SB_PATH_MTU_MASK) { + case CMDQ_MODIFY_QP_PATH_MTU_MTU_256: + return IB_MTU_256; + case CMDQ_MODIFY_QP_PATH_MTU_MTU_512: + return IB_MTU_512; + case CMDQ_MODIFY_QP_PATH_MTU_MTU_1024: + return IB_MTU_1024; + case CMDQ_MODIFY_QP_PATH_MTU_MTU_2048: + return IB_MTU_2048; + case CMDQ_MODIFY_QP_PATH_MTU_MTU_4096: + return IB_MTU_4096; + case CMDQ_MODIFY_QP_PATH_MTU_MTU_8192: + return IB_MTU_8192; + default: + return IB_MTU_2048; + } +} + +static inline enum ib_qp_state __to_ib_qp_state(u8 state) +{ + switch (state) { + case CMDQ_MODIFY_QP_NEW_STATE_RESET: + return IB_QPS_RESET; + case CMDQ_MODIFY_QP_NEW_STATE_INIT: + return IB_QPS_INIT; + case CMDQ_MODIFY_QP_NEW_STATE_RTR: + return IB_QPS_RTR; + case CMDQ_MODIFY_QP_NEW_STATE_RTS: + return IB_QPS_RTS; + case CMDQ_MODIFY_QP_NEW_STATE_SQD: + return IB_QPS_SQD; + case CMDQ_MODIFY_QP_NEW_STATE_SQE: + return IB_QPS_SQE; + case CMDQ_MODIFY_QP_NEW_STATE_ERR: + default: + return IB_QPS_ERR; + } +} + +static inline int bnxt_re_init_pow2_flag(struct bnxt_re_uctx_req *req, + struct bnxt_re_uctx_resp *resp) +{ + resp->comp_mask |= BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED; + if (!(req->comp_mask & BNXT_RE_COMP_MASK_REQ_UCNTX_POW2_SUPPORT)) { + resp->comp_mask &= ~BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED; + return -EINVAL; + } + return 0; +} + +static inline u32 bnxt_re_init_depth(u32 ent, struct bnxt_re_ucontext *uctx) +{ + return uctx ? (uctx->cmask & BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED) ? + ent : roundup_pow_of_two(ent) : ent; +} + +static inline int bnxt_re_init_rsvd_wqe_flag(struct bnxt_re_uctx_req *req, + struct bnxt_re_uctx_resp *resp, + bool genp5) +{ + resp->comp_mask |= BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED; + if (!(req->comp_mask & BNXT_RE_COMP_MASK_REQ_UCNTX_RSVD_WQE)) { + resp->comp_mask &= ~BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED; + return -EINVAL; + } else if (!genp5) { + resp->comp_mask &= ~BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED; + } + return 0; +} + +static inline u32 bnxt_re_get_diff(struct bnxt_re_ucontext *uctx, + struct bnxt_qplib_chip_ctx *cctx) +{ + if (!uctx) { + /* return res-wqe only for gen p4 for user resource */ + return _is_chip_gen_p5_p7(cctx) ? 0 : BNXT_QPLIB_RESERVED_QP_WRS; + } else if (uctx->cmask & BNXT_RE_COMP_MASK_UCNTX_RSVD_WQE_DISABLED) { + return 0; + } + /* old lib */ + return BNXT_QPLIB_RESERVED_QP_WRS; +} + +static inline void bnxt_re_init_qpmtu(struct bnxt_re_qp *qp, int mtu, + int mask, struct ib_qp_attr *qp_attr, + bool *is_qpmtu_high) +{ + int qpmtu, qpmtu_int; + int ifmtu, ifmtu_int; + + ifmtu = iboe_get_mtu(mtu); + ifmtu_int = ib_mtu_enum_to_int(ifmtu); + qpmtu = ifmtu; + qpmtu_int = ifmtu_int; + if (mask & IB_QP_PATH_MTU) { + qpmtu = qp_attr->path_mtu; + qpmtu_int = ib_mtu_enum_to_int(qpmtu); + if (qpmtu_int > ifmtu_int) { + /* Trim the QP path mtu to interface mtu and update + * the new mtu to user qp for retransmission psn + * calculations. + */ + qpmtu = ifmtu; + qpmtu_int = ifmtu_int; + *is_qpmtu_high = true; + } + } + qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu); + qp->qplib_qp.mtu = qpmtu_int; + qp->qplib_qp.modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU; +} + +inline unsigned long compare_ether_header(void *a, void *b) +{ + u32 *a32 = (u32 *)((u8 *)a + 2); + u32 *b32 = (u32 *)((u8 *)b + 2); + + return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | + (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); +} + +struct vlan_hdr { + __be16 h_vlan_TCI; + __be16 h_vlan_encapsulated_proto; +}; + +inline uint16_t +crc16(uint16_t crc, const void *buffer, unsigned int len) +{ + const unsigned char *cp = buffer; + /* CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1). */ + static uint16_t const crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 + }; + + while (len--) + crc = (((crc >> 8) & 0xffU) ^ + crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU; + return crc; +} + +static inline int __bnxt_re_set_vma_data(void *bnxt_re_uctx, + struct vm_area_struct *vma) +{ + return 0; +} + +static inline bool bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev, + u16 vlan_id) +{ + bool ret = true; + /* + * Check if the vlan is configured in the host. + * If not configured, it can be a transparent + * VLAN. So dont report the vlan id. + */ + return ret; +} + +#endif diff --git a/sys/dev/bnxt/bnxt_re/main.c b/sys/dev/bnxt/bnxt_re/main.c new file mode 100644 index 000000000000..3d26d21f3fc7 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/main.c @@ -0,0 +1,4467 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Main component of the bnxt_re driver + */ + +#include <linux/if_ether.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/pci.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/fs.h> +#include <rdma/ib_user_verbs.h> +#include <rdma/ib_addr.h> +#include <rdma/ib_cache.h> +#include <dev/mlx5/port.h> +#include <dev/mlx5/vport.h> +#include <linux/list.h> +#include <rdma/ib_smi.h> +#include <rdma/ib_umem.h> +#include <linux/in.h> +#include <linux/etherdevice.h> + +#include "bnxt_re.h" +#include "ib_verbs.h" +#include "bnxt_re-abi.h" +#include "bnxt.h" + +static char drv_version[] = + "Broadcom NetXtreme-C/E RoCE Driver " ROCE_DRV_MODULE_NAME \ + " v" ROCE_DRV_MODULE_VERSION " (" ROCE_DRV_MODULE_RELDATE ")\n"; + +#define BNXT_RE_DESC "Broadcom NetXtreme RoCE" +#define BNXT_ADEV_NAME "if_bnxt" + +MODULE_DESCRIPTION("Broadcom NetXtreme-C/E RoCE Driver"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DEPEND(bnxt_re, linuxkpi, 1, 1, 1); +MODULE_DEPEND(bnxt_re, ibcore, 1, 1, 1); +MODULE_DEPEND(bnxt_re, if_bnxt, 1, 1, 1); +MODULE_VERSION(bnxt_re, 1); + + +DEFINE_MUTEX(bnxt_re_mutex); /* mutex lock for driver */ + +static unsigned int restrict_mrs = 0; +module_param(restrict_mrs, uint, 0); +MODULE_PARM_DESC(restrict_mrs, " Restrict the no. of MRs 0 = 256K , 1 = 64K"); + +unsigned int restrict_stats = 0; +module_param(restrict_stats, uint, 0); +MODULE_PARM_DESC(restrict_stats, "Restrict stats query frequency to ethtool coalesce value. Disabled by default"); + +unsigned int enable_fc = 1; +module_param(enable_fc, uint, 0); +MODULE_PARM_DESC(enable_fc, "Enable default PFC, CC,ETS during driver load. 1 - fc enable, 0 - fc disable - Default is 1"); + +unsigned int min_tx_depth = 1; +module_param(min_tx_depth, uint, 0); +MODULE_PARM_DESC(min_tx_depth, "Minimum TX depth - Default is 1"); + +static uint8_t max_msix_vec[BNXT_RE_MAX_DEVICES] = {0}; +static unsigned int max_msix_vec_argc; +module_param_array(max_msix_vec, byte, &max_msix_vec_argc, 0444); +MODULE_PARM_DESC(max_msix_vec, "Max MSI-x vectors per PF (2 - 64) - Default is 64"); + +unsigned int cmdq_shadow_qd = RCFW_CMD_NON_BLOCKING_SHADOW_QD; +module_param_named(cmdq_shadow_qd, cmdq_shadow_qd, uint, 0644); +MODULE_PARM_DESC(cmdq_shadow_qd, "Perf Stat Debug: Shadow QD Range (1-64) - Default is 64"); + + +/* globals */ +struct list_head bnxt_re_dev_list = LINUX_LIST_HEAD_INIT(bnxt_re_dev_list); +static int bnxt_re_probe_count; + +DEFINE_MUTEX(bnxt_re_dev_lock); +static u32 gmod_exit; +static u32 gadd_dev_inprogress; + +static void bnxt_re_task(struct work_struct *work_task); +static struct workqueue_struct *bnxt_re_wq; +static int bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev); +static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len, + u32 *offset); +static int bnxt_re_ib_init(struct bnxt_re_dev *rdev); +static void bnxt_re_ib_init_2(struct bnxt_re_dev *rdev); +void _bnxt_re_remove(struct auxiliary_device *adev); +void writel_fbsd(struct bnxt_softc *bp, u32, u8, u32); +u32 readl_fbsd(struct bnxt_softc *bp, u32, u8); +static int bnxt_re_hwrm_dbr_pacing_qcfg(struct bnxt_re_dev *rdev); + +int bnxt_re_register_netdevice_notifier(struct notifier_block *nb) +{ + int rc; + rc = register_netdevice_notifier(nb); + return rc; +} + +int bnxt_re_unregister_netdevice_notifier(struct notifier_block *nb) +{ + int rc; + rc = unregister_netdevice_notifier(nb); + return rc; +} + +void bnxt_re_set_dma_device(struct ib_device *ibdev, struct bnxt_re_dev *rdev) +{ + ibdev->dma_device = &rdev->en_dev->pdev->dev; +} + +void bnxt_re_init_resolve_wq(struct bnxt_re_dev *rdev) +{ + rdev->resolve_wq = create_singlethread_workqueue("bnxt_re_resolve_wq"); + INIT_LIST_HEAD(&rdev->mac_wq_list); +} + +void bnxt_re_uninit_resolve_wq(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_resolve_dmac_work *tmp_work = NULL, *tmp_st; + if (!rdev->resolve_wq) + return; + flush_workqueue(rdev->resolve_wq); + list_for_each_entry_safe(tmp_work, tmp_st, &rdev->mac_wq_list, list) { + list_del(&tmp_work->list); + kfree(tmp_work); + } + destroy_workqueue(rdev->resolve_wq); + rdev->resolve_wq = NULL; +} + +u32 readl_fbsd(struct bnxt_softc *bp, u32 reg_off, u8 bar_idx) +{ + + if (bar_idx) + return bus_space_read_8(bp->doorbell_bar.tag, bp->doorbell_bar.handle, reg_off); + else + return bus_space_read_8(bp->hwrm_bar.tag, bp->hwrm_bar.handle, reg_off); +} + +void writel_fbsd(struct bnxt_softc *bp, u32 reg_off, u8 bar_idx, u32 val) +{ + if (bar_idx) + bus_space_write_8(bp->doorbell_bar.tag, bp->doorbell_bar.handle, reg_off, htole32(val)); + else + bus_space_write_8(bp->hwrm_bar.tag, bp->hwrm_bar.handle, reg_off, htole32(val)); +} + +static void bnxt_re_update_fifo_occup_slabs(struct bnxt_re_dev *rdev, + u32 fifo_occup) +{ + if (fifo_occup > rdev->dbg_stats->dbq.fifo_occup_water_mark) + rdev->dbg_stats->dbq.fifo_occup_water_mark = fifo_occup; + + if (fifo_occup > 8 * rdev->pacing_algo_th) + rdev->dbg_stats->dbq.fifo_occup_slab_4++; + else if (fifo_occup > 4 * rdev->pacing_algo_th) + rdev->dbg_stats->dbq.fifo_occup_slab_3++; + else if (fifo_occup > 2 * rdev->pacing_algo_th) + rdev->dbg_stats->dbq.fifo_occup_slab_2++; + else if (fifo_occup > rdev->pacing_algo_th) + rdev->dbg_stats->dbq.fifo_occup_slab_1++; +} + +static void bnxt_re_update_do_pacing_slabs(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data; + + if (pacing_data->do_pacing > rdev->dbg_stats->dbq.do_pacing_water_mark) + rdev->dbg_stats->dbq.do_pacing_water_mark = pacing_data->do_pacing; + + if (pacing_data->do_pacing > 16 * rdev->dbr_def_do_pacing) + rdev->dbg_stats->dbq.do_pacing_slab_5++; + else if (pacing_data->do_pacing > 8 * rdev->dbr_def_do_pacing) + rdev->dbg_stats->dbq.do_pacing_slab_4++; + else if (pacing_data->do_pacing > 4 * rdev->dbr_def_do_pacing) + rdev->dbg_stats->dbq.do_pacing_slab_3++; + else if (pacing_data->do_pacing > 2 * rdev->dbr_def_do_pacing) + rdev->dbg_stats->dbq.do_pacing_slab_2++; + else if (pacing_data->do_pacing > rdev->dbr_def_do_pacing) + rdev->dbg_stats->dbq.do_pacing_slab_1++; +} + +static bool bnxt_re_is_qp1_qp(struct bnxt_re_qp *qp) +{ + return qp->ib_qp.qp_type == IB_QPT_GSI; +} + +static struct bnxt_re_qp *bnxt_re_get_qp1_qp(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_qp *qp; + + mutex_lock(&rdev->qp_lock); + list_for_each_entry(qp, &rdev->qp_list, list) { + if (bnxt_re_is_qp1_qp(qp)) { + mutex_unlock(&rdev->qp_lock); + return qp; + } + } + mutex_unlock(&rdev->qp_lock); + return NULL; +} + +/* Set the maximum number of each resource that the driver actually wants + * to allocate. This may be up to the maximum number the firmware has + * reserved for the function. The driver may choose to allocate fewer + * resources than the firmware maximum. + */ +static void bnxt_re_limit_pf_res(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_max_res dev_res = {}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_qplib_dev_attr *attr; + struct bnxt_qplib_ctx *hctx; + int i; + + attr = rdev->dev_attr; + hctx = rdev->qplib_res.hctx; + cctx = rdev->chip_ctx; + + bnxt_qplib_max_res_supported(cctx, &rdev->qplib_res, &dev_res, false); + if (!_is_chip_gen_p5_p7(cctx)) { + hctx->qp_ctx.max = min_t(u32, dev_res.max_qp, attr->max_qp); + hctx->mrw_ctx.max = min_t(u32, dev_res.max_mr, attr->max_mr); + /* To accommodate 16k MRs and 16k AHs, + * driver has to allocate 32k backing store memory + */ + hctx->mrw_ctx.max *= 2; + hctx->srq_ctx.max = min_t(u32, dev_res.max_srq, attr->max_srq); + hctx->cq_ctx.max = min_t(u32, dev_res.max_cq, attr->max_cq); + for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) + hctx->tqm_ctx.qcount[i] = attr->tqm_alloc_reqs[i]; + } else { + hctx->qp_ctx.max = attr->max_qp ? attr->max_qp : dev_res.max_qp; + hctx->mrw_ctx.max = attr->max_mr ? attr->max_mr : dev_res.max_mr; + hctx->srq_ctx.max = attr->max_srq ? attr->max_srq : dev_res.max_srq; + hctx->cq_ctx.max = attr->max_cq ? attr->max_cq : dev_res.max_cq; + } +} + +static void bnxt_re_limit_vf_res(struct bnxt_re_dev *rdev, + struct bnxt_qplib_vf_res *vf_res, + u32 num_vf) +{ + struct bnxt_qplib_chip_ctx *cctx = rdev->chip_ctx; + struct bnxt_qplib_max_res dev_res = {}; + + bnxt_qplib_max_res_supported(cctx, &rdev->qplib_res, &dev_res, true); + vf_res->max_qp = dev_res.max_qp / num_vf; + vf_res->max_srq = dev_res.max_srq / num_vf; + vf_res->max_cq = dev_res.max_cq / num_vf; + /* + * MR and AH shares the same backing store, the value specified + * for max_mrw is split into half by the FW for MR and AH + */ + vf_res->max_mrw = dev_res.max_mr * 2 / num_vf; + vf_res->max_gid = BNXT_RE_MAX_GID_PER_VF; +} + +static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_ctx *hctx; + + hctx = rdev->qplib_res.hctx; + memset(&hctx->vf_res, 0, sizeof(struct bnxt_qplib_vf_res)); + bnxt_re_limit_pf_res(rdev); + + if (rdev->num_vfs) + bnxt_re_limit_vf_res(rdev, &hctx->vf_res, rdev->num_vfs); +} + +static void bnxt_re_dettach_irq(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_rcfw *rcfw = NULL; + struct bnxt_qplib_nq *nq; + int indx; + + rcfw = &rdev->rcfw; + for (indx = 0; indx < rdev->nqr.max_init; indx++) { + nq = &rdev->nqr.nq[indx]; + mutex_lock(&nq->lock); + bnxt_qplib_nq_stop_irq(nq, false); + mutex_unlock(&nq->lock); + } + + bnxt_qplib_rcfw_stop_irq(rcfw, false); +} + +static void bnxt_re_detach_err_device(struct bnxt_re_dev *rdev) +{ + /* Free the MSIx vectors only so that L2 can proceed with MSIx disable */ + bnxt_re_dettach_irq(rdev); + + /* Set the state as detached to prevent sending any more commands */ + set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); + set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); + wake_up_all(&rdev->rcfw.cmdq.waitq); +} + +#define MAX_DSCP_PRI_TUPLE 64 + +struct bnxt_re_dcb_work { + struct work_struct work; + struct bnxt_re_dev *rdev; + struct hwrm_async_event_cmpl cmpl; +}; + +static void bnxt_re_init_dcb_wq(struct bnxt_re_dev *rdev) +{ + rdev->dcb_wq = create_singlethread_workqueue("bnxt_re_dcb_wq"); +} + +static void bnxt_re_uninit_dcb_wq(struct bnxt_re_dev *rdev) +{ + if (!rdev->dcb_wq) + return; + flush_workqueue(rdev->dcb_wq); + destroy_workqueue(rdev->dcb_wq); + rdev->dcb_wq = NULL; +} + +static void bnxt_re_init_aer_wq(struct bnxt_re_dev *rdev) +{ + rdev->aer_wq = create_singlethread_workqueue("bnxt_re_aer_wq"); +} + +static void bnxt_re_uninit_aer_wq(struct bnxt_re_dev *rdev) +{ + if (!rdev->aer_wq) + return; + flush_workqueue(rdev->aer_wq); + destroy_workqueue(rdev->aer_wq); + rdev->aer_wq = NULL; +} + +static int bnxt_re_update_qp1_tos_dscp(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_qp *qp; + + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + return 0; + + qp = bnxt_re_get_qp1_qp(rdev); + if (!qp) + return 0; + + qp->qplib_qp.modify_flags = CMDQ_MODIFY_QP_MODIFY_MASK_TOS_DSCP; + qp->qplib_qp.tos_dscp = rdev->cc_param.qp1_tos_dscp; + + return bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp); +} + +static void bnxt_re_reconfigure_dscp(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_cc_param *cc_param; + struct bnxt_re_tc_rec *tc_rec; + bool update_cc = false; + u8 dscp_user; + int rc; + + cc_param = &rdev->cc_param; + tc_rec = &rdev->tc_rec[0]; + + if (!(cc_param->roce_dscp_user || cc_param->cnp_dscp_user)) + return; + + if (cc_param->cnp_dscp_user) { + dscp_user = (cc_param->cnp_dscp_user & 0x3f); + if ((tc_rec->cnp_dscp_bv & (1ul << dscp_user)) && + (cc_param->alt_tos_dscp != dscp_user)) { + cc_param->alt_tos_dscp = dscp_user; + cc_param->mask |= CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP; + update_cc = true; + } + } + + if (cc_param->roce_dscp_user) { + dscp_user = (cc_param->roce_dscp_user & 0x3f); + if ((tc_rec->roce_dscp_bv & (1ul << dscp_user)) && + (cc_param->tos_dscp != dscp_user)) { + cc_param->tos_dscp = dscp_user; + cc_param->mask |= CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP; + update_cc = true; + } + } + + if (update_cc) { + rc = bnxt_qplib_modify_cc(&rdev->qplib_res, cc_param); + if (rc) + dev_err(rdev_to_dev(rdev), "Failed to apply cc settings\n"); + } +} + +static void bnxt_re_dcb_wq_task(struct work_struct *work) +{ + struct bnxt_qplib_cc_param *cc_param; + struct bnxt_re_tc_rec *tc_rec; + struct bnxt_re_dev *rdev; + struct bnxt_re_dcb_work *dcb_work = + container_of(work, struct bnxt_re_dcb_work, work); + int rc; + + rdev = dcb_work->rdev; + if (!rdev) + goto exit; + + mutex_lock(&rdev->cc_lock); + + cc_param = &rdev->cc_param; + rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, cc_param); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to query ccparam rc:%d", rc); + goto fail; + } + tc_rec = &rdev->tc_rec[0]; + /* + * Upon the receival of DCB Async event: + * If roce_dscp or cnp_dscp or both (which user configured using configfs) + * is in the list, re-program the value using modify_roce_cc command + */ + bnxt_re_reconfigure_dscp(rdev); + + cc_param->roce_pri = tc_rec->roce_prio; + if (cc_param->qp1_tos_dscp != cc_param->tos_dscp) { + cc_param->qp1_tos_dscp = cc_param->tos_dscp; + rc = bnxt_re_update_qp1_tos_dscp(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), "%s:Failed to modify QP1 rc:%d", + __func__, rc); + goto fail; + } + } + +fail: + mutex_unlock(&rdev->cc_lock); +exit: + kfree(dcb_work); +} + +static int bnxt_re_hwrm_dbr_pacing_broadcast_event(struct bnxt_re_dev *rdev) +{ + struct hwrm_func_dbr_pacing_broadcast_event_output resp = {0}; + struct hwrm_func_dbr_pacing_broadcast_event_input req = {0}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_DBR_PACING_BROADCAST_EVENT, -1, -1); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_dbg(rdev_to_dev(rdev), + "Failed to send dbr pacing broadcast event rc:%d", rc); + return rc; + } + return 0; +} + +static int bnxt_re_hwrm_dbr_pacing_nqlist_query(struct bnxt_re_dev *rdev) +{ + struct hwrm_func_dbr_pacing_nqlist_query_output resp = {0}; + struct hwrm_func_dbr_pacing_nqlist_query_input req = {0}; + struct bnxt_dbq_nq_list *nq_list = &rdev->nq_list; + struct bnxt_en_dev *en_dev = rdev->en_dev; + bool primary_found = false; + struct bnxt_fw_msg fw_msg; + struct bnxt_qplib_nq *nq; + int rc, i, j = 1; + u16 *nql_ptr; + + nq = &rdev->nqr.nq[0]; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_DBR_PACING_NQLIST_QUERY, -1, -1); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to send dbr pacing nq list query rc:%d", rc); + return rc; + } + nq_list->num_nql_entries = le32_to_cpu(resp.num_nqs); + nql_ptr = &resp.nq_ring_id0; + /* populate the nq_list of the primary function with list received + * from FW. Fill the NQ IDs of secondary functions from index 1 to + * num_nql_entries - 1. Fill the nq_list->nq_id[0] with the + * nq_id of the primary pf + */ + for (i = 0; i < nq_list->num_nql_entries; i++) { + u16 nq_id = *nql_ptr; + + dev_dbg(rdev_to_dev(rdev), + "nq_list->nq_id[%d] = %d\n", i, nq_id); + if (nq_id != nq->ring_id) { + nq_list->nq_id[j] = nq_id; + j++; + } else { + primary_found = true; + nq_list->nq_id[0] = nq->ring_id; + } + nql_ptr++; + } + if (primary_found) + bnxt_qplib_dbr_pacing_set_primary_pf(rdev->chip_ctx, 1); + + return 0; +} + +static void __wait_for_fifo_occupancy_below_th(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data; + u32 read_val, fifo_occup; + bool first_read = true; + + /* loop shouldn't run infintely as the occupancy usually goes + * below pacing algo threshold as soon as pacing kicks in. + */ + while (1) { + read_val = readl_fbsd(rdev->en_dev->softc, rdev->dbr_db_fifo_reg_off, 0); + fifo_occup = pacing_data->fifo_max_depth - + ((read_val & pacing_data->fifo_room_mask) >> + pacing_data->fifo_room_shift); + /* Fifo occupancy cannot be greater the MAX FIFO depth */ + if (fifo_occup > pacing_data->fifo_max_depth) + break; + + if (first_read) { + bnxt_re_update_fifo_occup_slabs(rdev, fifo_occup); + first_read = false; + } + if (fifo_occup < pacing_data->pacing_th) + break; + } +} + +static void bnxt_re_set_default_pacing_data(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data; + + pacing_data->do_pacing = rdev->dbr_def_do_pacing; + pacing_data->pacing_th = rdev->pacing_algo_th; + pacing_data->alarm_th = + pacing_data->pacing_th * BNXT_RE_PACING_ALARM_TH_MULTIPLE(rdev->chip_ctx); +} + +#define CAG_RING_MASK 0x7FF +#define CAG_RING_SHIFT 17 +#define WATERMARK_MASK 0xFFF +#define WATERMARK_SHIFT 0 + +static bool bnxt_re_check_if_dbq_intr_triggered(struct bnxt_re_dev *rdev) +{ + u32 read_val; + int j; + + for (j = 0; j < 10; j++) { + read_val = readl_fbsd(rdev->en_dev->softc, rdev->dbr_aeq_arm_reg_off, 0); + dev_dbg(rdev_to_dev(rdev), "AEQ ARM status = 0x%x\n", + read_val); + if (!read_val) + return true; + } + return false; +} + +int bnxt_re_set_dbq_throttling_reg(struct bnxt_re_dev *rdev, u16 nq_id, u32 throttle) +{ + u32 cag_ring_water_mark = 0, read_val; + u32 throttle_val; + + /* Convert throttle percentage to value */ + throttle_val = (rdev->qplib_res.pacing_data->fifo_max_depth * throttle) / 100; + + if (bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { + cag_ring_water_mark = (nq_id & CAG_RING_MASK) << CAG_RING_SHIFT | + (throttle_val & WATERMARK_MASK); + writel_fbsd(rdev->en_dev->softc, rdev->dbr_throttling_reg_off, 0, cag_ring_water_mark); + read_val = readl_fbsd(rdev->en_dev->softc , rdev->dbr_throttling_reg_off, 0); + dev_dbg(rdev_to_dev(rdev), + "%s: dbr_throttling_reg_off read_val = 0x%x\n", + __func__, read_val); + if (read_val != cag_ring_water_mark) { + dev_dbg(rdev_to_dev(rdev), + "nq_id = %d write_val=0x%x read_val=0x%x\n", + nq_id, cag_ring_water_mark, read_val); + return 1; + } + } + writel_fbsd(rdev->en_dev->softc, rdev->dbr_aeq_arm_reg_off, 0, 1); + return 0; +} + +static void bnxt_re_set_dbq_throttling_for_non_primary(struct bnxt_re_dev *rdev) +{ + struct bnxt_dbq_nq_list *nq_list; + struct bnxt_qplib_nq *nq; + int i; + + nq_list = &rdev->nq_list; + /* Run a loop for other Active functions if this is primary function */ + if (bnxt_qplib_dbr_pacing_is_primary_pf(rdev->chip_ctx)) { + dev_dbg(rdev_to_dev(rdev), "%s: nq_list->num_nql_entries= %d\n", + __func__, nq_list->num_nql_entries); + nq = &rdev->nqr.nq[0]; + for (i = nq_list->num_nql_entries - 1; i > 0; i--) { + u16 nq_id = nq_list->nq_id[i]; + if (nq) + dev_dbg(rdev_to_dev(rdev), + "%s: nq_id = %d cur_fn_ring_id = %d\n", + __func__, nq_id, nq->ring_id); + if (bnxt_re_set_dbq_throttling_reg + (rdev, nq_id, 0)) + break; + bnxt_re_check_if_dbq_intr_triggered(rdev); + } + } +} + +static void bnxt_re_handle_dbr_nq_pacing_notification(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_nq *nq; + int rc = 0; + + nq = &rdev->nqr.nq[0]; + + /* Query the NQ list*/ + rc = bnxt_re_hwrm_dbr_pacing_nqlist_query(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to Query NQ list rc= %d", rc); + return; + } + /*Configure GRC access for Throttling and aeq_arm register */ + writel_fbsd(rdev->en_dev->softc, BNXT_GRCPF_REG_WINDOW_BASE_OUT + 28, 0, + rdev->chip_ctx->dbr_aeq_arm_reg & BNXT_GRC_BASE_MASK); + + rdev->dbr_throttling_reg_off = + (rdev->chip_ctx->dbr_throttling_reg & + BNXT_GRC_OFFSET_MASK) + 0x8000; + rdev->dbr_aeq_arm_reg_off = + (rdev->chip_ctx->dbr_aeq_arm_reg & + BNXT_GRC_OFFSET_MASK) + 0x8000; + + bnxt_re_set_dbq_throttling_reg(rdev, nq->ring_id, rdev->dbq_watermark); +} + +static void bnxt_re_dbq_wq_task(struct work_struct *work) +{ + struct bnxt_re_dbq_work *dbq_work = + container_of(work, struct bnxt_re_dbq_work, work); + struct bnxt_re_dev *rdev; + + rdev = dbq_work->rdev; + + if (!rdev) + goto exit; + switch (dbq_work->event) { + case BNXT_RE_DBQ_EVENT_SCHED: + dev_dbg(rdev_to_dev(rdev), "%s: Handle DBQ Pacing event\n", + __func__); + if (!bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) + bnxt_re_hwrm_dbr_pacing_broadcast_event(rdev); + else + bnxt_re_pacing_alert(rdev); + break; + case BNXT_RE_DBR_PACING_EVENT: + dev_dbg(rdev_to_dev(rdev), "%s: Sched interrupt/pacing worker\n", + __func__); + if (_is_chip_p7(rdev->chip_ctx)) + bnxt_re_pacing_alert(rdev); + else if (!rdev->chip_ctx->modes.dbr_pacing_v0) + bnxt_re_hwrm_dbr_pacing_qcfg(rdev); + break; + case BNXT_RE_DBR_NQ_PACING_NOTIFICATION: + bnxt_re_handle_dbr_nq_pacing_notification(rdev); + /* Issue a broadcast event to notify other functions + * that primary changed + */ + bnxt_re_hwrm_dbr_pacing_broadcast_event(rdev); + break; + } +exit: + kfree(dbq_work); +} + +static void bnxt_re_async_notifier(void *handle, struct hwrm_async_event_cmpl *cmpl) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle); + struct bnxt_re_dcb_work *dcb_work; + struct bnxt_re_dbq_work *dbq_work; + struct bnxt_re_dev *rdev; + u16 event_id; + u32 data1; + u32 data2 = 0; + + if (!cmpl) { + pr_err("Async event, bad completion\n"); + return; + } + + if (!en_info || !en_info->en_dev) { + pr_err("Async event, bad en_info or en_dev\n"); + return; + } + rdev = en_info->rdev; + + event_id = le16_to_cpu(cmpl->event_id); + data1 = le32_to_cpu(cmpl->event_data1); + data2 = le32_to_cpu(cmpl->event_data2); + + if (!rdev || !rdev_to_dev(rdev)) { + dev_dbg(NULL, "Async event, bad rdev or netdev\n"); + return; + } + + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags) || + !test_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags)) { + dev_dbg(NULL, "Async event, device already detached\n"); + return; + } + if (data2 >= 0) + dev_dbg(rdev_to_dev(rdev), "Async event_id = %d data1 = %d data2 = %d", + event_id, data1, data2); + + switch (event_id) { + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE: + /* Not handling the event in older FWs */ + if (!is_qport_service_type_supported(rdev)) + break; + if (!rdev->dcb_wq) + break; + dcb_work = kzalloc(sizeof(*dcb_work), GFP_ATOMIC); + if (!dcb_work) + break; + + dcb_work->rdev = rdev; + memcpy(&dcb_work->cmpl, cmpl, sizeof(*cmpl)); + INIT_WORK(&dcb_work->work, bnxt_re_dcb_wq_task); + queue_work(rdev->dcb_wq, &dcb_work->work); + break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY: + if (EVENT_DATA1_RESET_NOTIFY_FATAL(data1)) { + /* Set rcfw flag to control commands send to Bono */ + set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); + /* Set bnxt_re flag to control commands send via L2 driver */ + set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); + wake_up_all(&rdev->rcfw.cmdq.waitq); + } + break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_THRESHOLD: + if (!rdev->dbr_pacing) + break; + dbq_work = kzalloc(sizeof(*dbq_work), GFP_ATOMIC); + if (!dbq_work) + goto unlock; + dbq_work->rdev = rdev; + dbq_work->event = BNXT_RE_DBR_PACING_EVENT; + INIT_WORK(&dbq_work->work, bnxt_re_dbq_wq_task); + queue_work(rdev->dbq_wq, &dbq_work->work); + rdev->dbr_sw_stats->dbq_int_recv++; + break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_NQ_UPDATE: + if (!rdev->dbr_pacing) + break; + + dbq_work = kzalloc(sizeof(*dbq_work), GFP_ATOMIC); + if (!dbq_work) + goto unlock; + dbq_work->rdev = rdev; + dbq_work->event = BNXT_RE_DBR_NQ_PACING_NOTIFICATION; + INIT_WORK(&dbq_work->work, bnxt_re_dbq_wq_task); + queue_work(rdev->dbq_wq, &dbq_work->work); + break; + + default: + break; + } +unlock: + return; +} + +static void bnxt_re_db_fifo_check(struct work_struct *work) +{ + struct bnxt_re_dev *rdev = container_of(work, struct bnxt_re_dev, + dbq_fifo_check_work); + struct bnxt_qplib_db_pacing_data *pacing_data; + u32 pacing_save; + + if (!mutex_trylock(&rdev->dbq_lock)) + return; + pacing_data = rdev->qplib_res.pacing_data; + pacing_save = rdev->do_pacing_save; + __wait_for_fifo_occupancy_below_th(rdev); + cancel_delayed_work_sync(&rdev->dbq_pacing_work); + if (rdev->dbr_recovery_on) + goto recovery_on; + if (pacing_save > rdev->dbr_def_do_pacing) { + /* Double the do_pacing value during the congestion */ + pacing_save = pacing_save << 1; + } else { + /* + * when a new congestion is detected increase the do_pacing + * by 8 times. And also increase the pacing_th by 4 times. The + * reason to increase pacing_th is to give more space for the + * queue to oscillate down without getting empty, but also more + * room for the queue to increase without causing another alarm. + */ + pacing_save = pacing_save << 3; + pacing_data->pacing_th = rdev->pacing_algo_th * 4; + } + + if (pacing_save > BNXT_RE_MAX_DBR_DO_PACING) + pacing_save = BNXT_RE_MAX_DBR_DO_PACING; + + pacing_data->do_pacing = pacing_save; + rdev->do_pacing_save = pacing_data->do_pacing; + pacing_data->alarm_th = + pacing_data->pacing_th * BNXT_RE_PACING_ALARM_TH_MULTIPLE(rdev->chip_ctx); +recovery_on: + schedule_delayed_work(&rdev->dbq_pacing_work, + msecs_to_jiffies(rdev->dbq_pacing_time)); + rdev->dbr_sw_stats->dbq_pacing_alerts++; + mutex_unlock(&rdev->dbq_lock); +} + +static void bnxt_re_pacing_timer_exp(struct work_struct *work) +{ + struct bnxt_re_dev *rdev = container_of(work, struct bnxt_re_dev, + dbq_pacing_work.work); + struct bnxt_qplib_db_pacing_data *pacing_data; + u32 read_val, fifo_occup; + struct bnxt_qplib_nq *nq; + + if (!mutex_trylock(&rdev->dbq_lock)) + return; + + pacing_data = rdev->qplib_res.pacing_data; + read_val = readl_fbsd(rdev->en_dev->softc , rdev->dbr_db_fifo_reg_off, 0); + fifo_occup = pacing_data->fifo_max_depth - + ((read_val & pacing_data->fifo_room_mask) >> + pacing_data->fifo_room_shift); + + if (fifo_occup > pacing_data->pacing_th) + goto restart_timer; + + /* + * Instead of immediately going back to the default do_pacing + * reduce it by 1/8 times and restart the timer. + */ + pacing_data->do_pacing = pacing_data->do_pacing - (pacing_data->do_pacing >> 3); + pacing_data->do_pacing = max_t(u32, rdev->dbr_def_do_pacing, pacing_data->do_pacing); + /* + * If the fifo_occup is less than the interrupt enable threshold + * enable the interrupt on the primary PF. + */ + if (rdev->dbq_int_disable && fifo_occup < rdev->pacing_en_int_th) { + if (bnxt_qplib_dbr_pacing_is_primary_pf(rdev->chip_ctx)) { + if (!rdev->chip_ctx->modes.dbr_pacing_v0) { + nq = &rdev->nqr.nq[0]; + bnxt_re_set_dbq_throttling_reg(rdev, nq->ring_id, + rdev->dbq_watermark); + rdev->dbr_sw_stats->dbq_int_en++; + rdev->dbq_int_disable = false; + } + } + } + if (pacing_data->do_pacing <= rdev->dbr_def_do_pacing) { + bnxt_re_set_default_pacing_data(rdev); + rdev->dbr_sw_stats->dbq_pacing_complete++; + goto dbq_unlock; + } +restart_timer: + schedule_delayed_work(&rdev->dbq_pacing_work, + msecs_to_jiffies(rdev->dbq_pacing_time)); + bnxt_re_update_do_pacing_slabs(rdev); + rdev->dbr_sw_stats->dbq_pacing_resched++; +dbq_unlock: + rdev->do_pacing_save = pacing_data->do_pacing; + mutex_unlock(&rdev->dbq_lock); +} + +void bnxt_re_pacing_alert(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_db_pacing_data *pacing_data; + + if (!rdev->dbr_pacing) + return; + mutex_lock(&rdev->dbq_lock); + pacing_data = rdev->qplib_res.pacing_data; + + /* + * Increase the alarm_th to max so that other user lib instances do not + * keep alerting the driver. + */ + pacing_data->alarm_th = pacing_data->fifo_max_depth; + pacing_data->do_pacing = BNXT_RE_MAX_DBR_DO_PACING; + cancel_work_sync(&rdev->dbq_fifo_check_work); + schedule_work(&rdev->dbq_fifo_check_work); + mutex_unlock(&rdev->dbq_lock); +} + +void bnxt_re_schedule_dbq_event(struct bnxt_qplib_res *res) +{ + struct bnxt_re_dbq_work *dbq_work; + struct bnxt_re_dev *rdev; + + rdev = container_of(res, struct bnxt_re_dev, qplib_res); + + atomic_set(&rdev->dbq_intr_running, 1); + + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + goto exit; + /* Run the loop to send dbq event to other functions + * for newer FW + */ + if (bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx) && + !rdev->chip_ctx->modes.dbr_pacing_v0) + bnxt_re_set_dbq_throttling_for_non_primary(rdev); + + dbq_work = kzalloc(sizeof(*dbq_work), GFP_ATOMIC); + if (!dbq_work) + goto exit; + dbq_work->rdev = rdev; + dbq_work->event = BNXT_RE_DBQ_EVENT_SCHED; + INIT_WORK(&dbq_work->work, bnxt_re_dbq_wq_task); + queue_work(rdev->dbq_wq, &dbq_work->work); + rdev->dbr_sw_stats->dbq_int_recv++; + rdev->dbq_int_disable = true; +exit: + atomic_set(&rdev->dbq_intr_running, 0); +} + +static void bnxt_re_free_msix(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + int rc; + + rc = en_dev->en_ops->bnxt_free_msix(rdev->en_dev, BNXT_ROCE_ULP); + if (rc) + dev_err(rdev_to_dev(rdev), "netdev %p free_msix failed! rc = 0x%x", + rdev->netdev, rc); +} + +static int bnxt_re_request_msix(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + int rc = 0, num_msix_want, num_msix_got; + struct bnxt_msix_entry *entry; + + /* + * Request MSIx based on the function type. This is + * a temporory solution to enable max VFs when NPAR is + * enabled. + * TODO - change the scheme with an adapter specific check + * as the latest adapters can support more NQs. For now + * this change satisfy all adapter versions. + */ + + if (rdev->is_virtfn) + num_msix_want = BNXT_RE_MAX_MSIX_VF; + else if (BNXT_EN_NPAR(en_dev)) + num_msix_want = BNXT_RE_MAX_MSIX_NPAR_PF; + else if (_is_chip_gen_p5_p7(rdev->chip_ctx)) + num_msix_want = rdev->num_msix_requested ?: BNXT_RE_MAX_MSIX_GEN_P5_PF; + else + num_msix_want = BNXT_RE_MAX_MSIX_PF; + + /* + * Since MSIX vectors are used for both NQs and CREQ, we should try to + * allocate num_online_cpus + 1 by taking into account the CREQ. This + * leaves the number of MSIX vectors for NQs match the number of CPUs + * and allows the system to be fully utilized + */ + num_msix_want = min_t(u32, num_msix_want, num_online_cpus() + 1); + num_msix_want = min_t(u32, num_msix_want, BNXT_RE_MAX_MSIX); + num_msix_want = max_t(u32, num_msix_want, BNXT_RE_MIN_MSIX); + + entry = rdev->nqr.msix_entries; + + num_msix_got = en_dev->en_ops->bnxt_request_msix(en_dev, BNXT_ROCE_ULP, + entry, num_msix_want); + if (num_msix_got < BNXT_RE_MIN_MSIX) { + rc = -EINVAL; + goto done; + } + if (num_msix_got != num_msix_want) + dev_warn(rdev_to_dev(rdev), + "bnxt_request_msix: wanted %d vectors, got %d\n", + num_msix_want, num_msix_got); + + rdev->nqr.num_msix = num_msix_got; + return 0; +done: + if (num_msix_got) + bnxt_re_free_msix(rdev); + return rc; +} + +static int __wait_for_ib_unregister(struct bnxt_re_dev *rdev, + struct bnxt_re_en_dev_info *en_info) +{ + u64 timeout = 0; + u32 cur_prod = 0, cur_cons = 0; + int retry = 0, rc = 0, ret = 0; + + cur_prod = rdev->rcfw.cmdq.hwq.prod; + cur_cons = rdev->rcfw.cmdq.hwq.cons; + timeout = msecs_to_jiffies(BNXT_RE_RECOVERY_IB_UNINIT_WAIT_TIME_MS); + retry = BNXT_RE_RECOVERY_IB_UNINIT_WAIT_RETRY; + /* During module exit, increase timeout ten-fold to 100 mins to wait + * as long as possible for ib_unregister() to complete + */ + if (rdev->mod_exit) + retry *= 10; + do { + /* + * Since the caller of this function invokes with bnxt_re_mutex held, + * release it to avoid holding a lock while in wait / sleep mode. + */ + mutex_unlock(&bnxt_re_mutex); + rc = wait_event_timeout(en_info->waitq, + en_info->ib_uninit_done, + timeout); + mutex_lock(&bnxt_re_mutex); + + if (!bnxt_re_is_rdev_valid(rdev)) + break; + + if (rc) + break; + + if (!RCFW_NO_FW_ACCESS(&rdev->rcfw)) { + /* No need to check for cmdq stall during module exit, + * wait for ib unregister to complete + */ + if (!rdev->mod_exit) + ret = __check_cmdq_stall(&rdev->rcfw, &cur_prod, &cur_cons); + if (ret || en_info->ib_uninit_done) + break; + } + } while (retry--); + + return rc; +} + +static int bnxt_re_handle_start(struct auxiliary_device *adev) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev); + struct bnxt_re_dev *rdev = NULL; + struct ifnet *real_dev; + struct bnxt_en_dev *en_dev; + struct ifnet *netdev; + int rc = 0; + + if (!en_info || !en_info->en_dev) { + pr_err("Start, bad en_info or en_dev\n"); + return -EINVAL; + } + netdev = en_info->en_dev->net; + if (en_info->rdev) { + dev_info(rdev_to_dev(en_info->rdev), + "%s: Device is already added adev %p rdev: %p\n", + __func__, adev, en_info->rdev); + return 0; + } + + en_dev = en_info->en_dev; + real_dev = rdma_vlan_dev_real_dev(netdev); + if (!real_dev) + real_dev = netdev; + rc = bnxt_re_add_device(&rdev, real_dev, + en_info->gsi_mode, + BNXT_RE_POST_RECOVERY_INIT, + en_info->wqe_mode, + en_info->num_msix_requested, adev); + if (rc) { + /* Add device failed. Unregister the device. + * This has to be done explicitly as + * bnxt_re_stop would not have unregistered + */ + rtnl_lock(); + en_dev->en_ops->bnxt_unregister_device(en_dev, BNXT_ROCE_ULP); + rtnl_unlock(); + mutex_lock(&bnxt_re_dev_lock); + gadd_dev_inprogress--; + mutex_unlock(&bnxt_re_dev_lock); + return rc; + } + rdev->adev = adev; + rtnl_lock(); + bnxt_re_get_link_speed(rdev); + rtnl_unlock(); + rc = bnxt_re_ib_init(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed ib_init\n"); + return rc; + } + bnxt_re_ib_init_2(rdev); + + return rc; +} + +static void bnxt_re_stop(void *handle) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle); + struct ifnet *netdev; + struct bnxt_re_dev *rdev; + struct bnxt_en_dev *en_dev; + int rc = 0; + + rtnl_unlock(); + mutex_lock(&bnxt_re_mutex); + if (!en_info || !en_info->en_dev) { + pr_err("Stop, bad en_info or en_dev\n"); + goto exit; + } + netdev = en_info->en_dev->net; + rdev = en_info->rdev; + if (!rdev) + goto exit; + + if (!bnxt_re_is_rdev_valid(rdev)) + goto exit; + + /* + * Check if fw has undergone reset or is in a fatal condition. + * If so, set flags so that no further commands are sent down to FW + */ + en_dev = rdev->en_dev; + if (en_dev->en_state & BNXT_STATE_FW_FATAL_COND || + en_dev->en_state & BNXT_STATE_FW_RESET_DET) { + /* Set rcfw flag to control commands send to Bono */ + set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); + /* Set bnxt_re flag to control commands send via L2 driver */ + set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); + wake_up_all(&rdev->rcfw.cmdq.waitq); + } + + if (test_bit(BNXT_RE_FLAG_STOP_IN_PROGRESS, &rdev->flags)) + goto exit; + set_bit(BNXT_RE_FLAG_STOP_IN_PROGRESS, &rdev->flags); + + en_info->wqe_mode = rdev->chip_ctx->modes.wqe_mode; + en_info->gsi_mode = rdev->gsi_ctx.gsi_qp_mode; + en_info->num_msix_requested = rdev->num_msix_requested; + en_info->ib_uninit_done = false; + + if (rdev->dbr_pacing) + bnxt_re_set_pacing_dev_state(rdev); + + dev_info(rdev_to_dev(rdev), "%s: L2 driver notified to stop." + "Attempting to stop and Dispatching event " + "to inform the stack\n", __func__); + init_waitqueue_head(&en_info->waitq); + /* Schedule a work item to handle IB UNINIT for recovery */ + bnxt_re_schedule_work(rdev, NETDEV_UNREGISTER, + NULL, netdev, rdev->adev); + rc = __wait_for_ib_unregister(rdev, en_info); + if (!bnxt_re_is_rdev_valid(rdev)) + goto exit; + if (!rc) { + dev_info(rdev_to_dev(rdev), "%s: Attempt to stop failed\n", + __func__); + bnxt_re_detach_err_device(rdev); + goto exit; + } + bnxt_re_remove_device(rdev, BNXT_RE_PRE_RECOVERY_REMOVE, rdev->adev); +exit: + mutex_unlock(&bnxt_re_mutex); + /* Take rtnl_lock before return, bnxt_re_stop is called with rtnl_lock */ + rtnl_lock(); + + return; +} + +static void bnxt_re_start(void *handle) +{ + rtnl_unlock(); + mutex_lock(&bnxt_re_mutex); + if (bnxt_re_handle_start((struct auxiliary_device *)handle)) + pr_err("Failed to start RoCE device"); + mutex_unlock(&bnxt_re_mutex); + /* Take rtnl_lock before return, bnxt_re_start is called with rtnl_lock */ + rtnl_lock(); + return; +} + +static void bnxt_re_shutdown(void *p) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(p); + struct bnxt_re_dev *rdev; + + if (!en_info) { + pr_err("Shutdown, bad en_info\n"); + return; + } + rtnl_unlock(); + mutex_lock(&bnxt_re_mutex); + rdev = en_info->rdev; + if (!rdev || !bnxt_re_is_rdev_valid(rdev)) + goto exit; + + /* rtnl_lock held by L2 before coming here */ + bnxt_re_stopqps_and_ib_uninit(rdev); + bnxt_re_remove_device(rdev, BNXT_RE_COMPLETE_REMOVE, rdev->adev); +exit: + mutex_unlock(&bnxt_re_mutex); + rtnl_lock(); + return; +} + +static void bnxt_re_stop_irq(void *handle) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle); + struct bnxt_qplib_rcfw *rcfw = NULL; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_nq *nq; + int indx; + + if (!en_info) { + pr_err("Stop irq, bad en_info\n"); + return; + } + rdev = en_info->rdev; + + if (!rdev) + return; + + rcfw = &rdev->rcfw; + for (indx = 0; indx < rdev->nqr.max_init; indx++) { + nq = &rdev->nqr.nq[indx]; + mutex_lock(&nq->lock); + bnxt_qplib_nq_stop_irq(nq, false); + mutex_unlock(&nq->lock); + } + + if (test_bit(BNXT_RE_FLAG_ALLOC_RCFW, &rdev->flags)) + bnxt_qplib_rcfw_stop_irq(rcfw, false); +} + +static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle); + struct bnxt_msix_entry *msix_ent = NULL; + struct bnxt_qplib_rcfw *rcfw = NULL; + struct bnxt_re_dev *rdev; + struct bnxt_qplib_nq *nq; + int indx, rc, vec; + + if (!en_info) { + pr_err("Start irq, bad en_info\n"); + return; + } + rdev = en_info->rdev; + if (!rdev) + return; + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + return; + msix_ent = rdev->nqr.msix_entries; + rcfw = &rdev->rcfw; + + if (!ent) { + /* Not setting the f/w timeout bit in rcfw. + * During the driver unload the first command + * to f/w will timeout and that will set the + * timeout bit. + */ + dev_err(rdev_to_dev(rdev), "Failed to re-start IRQs\n"); + return; + } + + /* Vectors may change after restart, so update with new vectors + * in device structure. + */ + for (indx = 0; indx < rdev->nqr.num_msix; indx++) + rdev->nqr.msix_entries[indx].vector = ent[indx].vector; + + if (test_bit(BNXT_RE_FLAG_ALLOC_RCFW, &rdev->flags)) { + rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector, + false); + if (rc) { + dev_warn(rdev_to_dev(rdev), + "Failed to reinit CREQ\n"); + return; + } + } + for (indx = 0 ; indx < rdev->nqr.max_init; indx++) { + nq = &rdev->nqr.nq[indx]; + vec = indx + 1; + rc = bnxt_qplib_nq_start_irq(nq, indx, msix_ent[vec].vector, + false); + if (rc) { + dev_warn(rdev_to_dev(rdev), + "Failed to reinit NQ index %d\n", indx); + return; + } + } +} + +/* + * Except for ulp_async_notifier, the remaining ulp_ops + * below are called with rtnl_lock held + */ +static struct bnxt_ulp_ops bnxt_re_ulp_ops = { + .ulp_async_notifier = bnxt_re_async_notifier, + .ulp_stop = bnxt_re_stop, + .ulp_start = bnxt_re_start, + .ulp_shutdown = bnxt_re_shutdown, + .ulp_irq_stop = bnxt_re_stop_irq, + .ulp_irq_restart = bnxt_re_start_irq, +}; + +static inline const char *bnxt_re_netevent(unsigned long event) +{ + BNXT_RE_NETDEV_EVENT(event, NETDEV_UP); + BNXT_RE_NETDEV_EVENT(event, NETDEV_DOWN); + BNXT_RE_NETDEV_EVENT(event, NETDEV_CHANGE); + BNXT_RE_NETDEV_EVENT(event, NETDEV_REGISTER); + BNXT_RE_NETDEV_EVENT(event, NETDEV_UNREGISTER); + BNXT_RE_NETDEV_EVENT(event, NETDEV_CHANGEADDR); + return "Unknown"; +} + +/* RoCE -> Net driver */ + +/* Driver registration routines used to let the networking driver (bnxt_en) + * to know that the RoCE driver is now installed */ +static void bnxt_re_unregister_netdev(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + int rc; + + rtnl_lock(); + rc = en_dev->en_ops->bnxt_unregister_device(rdev->en_dev, + BNXT_ROCE_ULP); + rtnl_unlock(); + if (rc) + dev_err(rdev_to_dev(rdev), "netdev %p unregister failed! rc = 0x%x", + rdev->en_dev->net, rc); + + clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); +} + +static int bnxt_re_register_netdev(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + int rc = 0; + + rtnl_lock(); + rc = en_dev->en_ops->bnxt_register_device(en_dev, + BNXT_ROCE_ULP, + &bnxt_re_ulp_ops, + rdev->adev); + rtnl_unlock(); + if (rc) { + dev_err(rdev_to_dev(rdev), "netdev %p register failed! rc = 0x%x", + rdev->netdev, rc); + return rc; + } + + return rc; +} + +static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_en_dev *en_dev; + struct bnxt_qplib_res *res; + u32 l2db_len = 0; + u32 offset = 0; + u32 barlen; + int rc; + + res = &rdev->qplib_res; + en_dev = rdev->en_dev; + cctx = rdev->chip_ctx; + + /* Issue qcfg */ + rc = bnxt_re_hwrm_qcfg(rdev, &l2db_len, &offset); + if (rc) + dev_info(rdev_to_dev(rdev), + "Couldn't get DB bar size, Low latency framework is disabled\n"); + /* set register offsets for both UC and WC */ + if (_is_chip_p7(cctx)) + res->dpi_tbl.ucreg.offset = offset; + else + res->dpi_tbl.ucreg.offset = res->is_vf ? BNXT_QPLIB_DBR_VF_DB_OFFSET : + BNXT_QPLIB_DBR_PF_DB_OFFSET; + res->dpi_tbl.wcreg.offset = res->dpi_tbl.ucreg.offset; + + /* If WC mapping is disabled by L2 driver then en_dev->l2_db_size + * is equal to the DB-Bar actual size. This indicates that L2 + * is mapping entire bar as UC-. RoCE driver can't enable WC mapping + * in such cases and DB-push will be disabled. + */ + barlen = pci_resource_len(res->pdev, RCFW_DBR_PCI_BAR_REGION); + if (cctx->modes.db_push && l2db_len && en_dev->l2_db_size != barlen) { + res->dpi_tbl.wcreg.offset = en_dev->l2_db_size; + dev_info(rdev_to_dev(rdev), + "Low latency framework is enabled\n"); + } + + return; +} + +static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) +{ + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_en_dev *en_dev; + + en_dev = rdev->en_dev; + cctx = rdev->chip_ctx; + cctx->modes.wqe_mode = _is_chip_gen_p5_p7(rdev->chip_ctx) ? + mode : BNXT_QPLIB_WQE_MODE_STATIC; + cctx->modes.te_bypass = false; + if (bnxt_re_hwrm_qcaps(rdev)) + dev_err(rdev_to_dev(rdev), + "Failed to query hwrm qcaps\n"); + /* + * TODO: Need a better mechanism for spreading of the + * 512 extended PPP pages in the presence of VF and + * NPAR, until then not enabling push + */ + if (_is_chip_p7(rdev->chip_ctx) && cctx->modes.db_push) { + if (rdev->is_virtfn || BNXT_EN_NPAR(en_dev)) + cctx->modes.db_push = false; + } + + rdev->roce_mode = en_dev->flags & BNXT_EN_FLAG_ROCE_CAP; + dev_dbg(rdev_to_dev(rdev), + "RoCE is supported on the device - caps:0x%x", + rdev->roce_mode); + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + rdev->roce_mode = BNXT_RE_FLAG_ROCEV2_CAP; + cctx->hw_stats_size = en_dev->hw_ring_stats_size; +} + +static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_chip_ctx *chip_ctx; + struct bnxt_qplib_res *res; + + if (!rdev->chip_ctx) + return; + + res = &rdev->qplib_res; + bnxt_qplib_unmap_db_bar(res); + + kfree(res->hctx); + res->rcfw = NULL; + kfree(rdev->dev_attr); + rdev->dev_attr = NULL; + + chip_ctx = rdev->chip_ctx; + rdev->chip_ctx = NULL; + res->cctx = NULL; + res->hctx = NULL; + res->pdev = NULL; + res->netdev = NULL; + kfree(chip_ctx); +} + +static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) +{ + struct bnxt_qplib_chip_ctx *chip_ctx; + struct bnxt_en_dev *en_dev; + int rc; + + en_dev = rdev->en_dev; + /* Supply pci device to qplib */ + rdev->qplib_res.pdev = en_dev->pdev; + rdev->qplib_res.netdev = rdev->netdev; + rdev->qplib_res.en_dev = en_dev; + + chip_ctx = kzalloc(sizeof(*chip_ctx), GFP_KERNEL); + if (!chip_ctx) + return -ENOMEM; + rdev->chip_ctx = chip_ctx; + rdev->qplib_res.cctx = chip_ctx; + rc = bnxt_re_query_hwrm_intf_version(rdev); + if (rc) + goto fail; + rdev->dev_attr = kzalloc(sizeof(*rdev->dev_attr), GFP_KERNEL); + if (!rdev->dev_attr) { + rc = -ENOMEM; + goto fail; + } + rdev->qplib_res.dattr = rdev->dev_attr; + rdev->qplib_res.rcfw = &rdev->rcfw; + rdev->qplib_res.is_vf = rdev->is_virtfn; + + rdev->qplib_res.hctx = kzalloc(sizeof(*rdev->qplib_res.hctx), + GFP_KERNEL); + if (!rdev->qplib_res.hctx) { + rc = -ENOMEM; + goto fail; + } + bnxt_re_set_drv_mode(rdev, wqe_mode); + + bnxt_re_set_db_offset(rdev); + rc = bnxt_qplib_map_db_bar(&rdev->qplib_res); + if (rc) + goto fail; + + rc = bnxt_qplib_enable_atomic_ops_to_root(en_dev->pdev); + if (rc) + dev_dbg(rdev_to_dev(rdev), + "platform doesn't support global atomics"); + + return 0; +fail: + kfree(rdev->chip_ctx); + rdev->chip_ctx = NULL; + + kfree(rdev->dev_attr); + rdev->dev_attr = NULL; + + kfree(rdev->qplib_res.hctx); + rdev->qplib_res.hctx = NULL; + return rc; +} + +static u16 bnxt_re_get_rtype(struct bnxt_re_dev *rdev) { + return _is_chip_gen_p5_p7(rdev->chip_ctx) ? + HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ : + HWRM_RING_ALLOC_INPUT_RING_TYPE_ROCE_CMPL; +} + +static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, u16 fw_ring_id) +{ + int rc = -EINVAL; + struct hwrm_ring_free_input req = {0}; + struct hwrm_ring_free_output resp; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + + if (!en_dev) + return rc; + + /* To avoid unnecessary error messages during recovery. + * HW is anyway in error state. So dont send down the command */ + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + return 0; + + /* allocation had failed, no need to issue hwrm */ + if (fw_ring_id == 0xffff) + return 0; + + memset(&fw_msg, 0, sizeof(fw_msg)); + + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_FREE, -1, -1); + req.ring_type = bnxt_re_get_rtype(rdev); + req.ring_id = cpu_to_le16(fw_ring_id); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to free HW ring with rc = 0x%x", rc); + return rc; + } + dev_dbg(rdev_to_dev(rdev), "HW ring freed with id = 0x%x\n", + fw_ring_id); + + return rc; +} + +static int bnxt_re_net_ring_alloc(struct bnxt_re_dev *rdev, + struct bnxt_re_ring_attr *ring_attr, + u16 *fw_ring_id) +{ + int rc = -EINVAL; + struct hwrm_ring_alloc_input req = {0}; + struct hwrm_ring_alloc_output resp; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + + if (!en_dev) + return rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_ALLOC, -1, -1); + req.flags = cpu_to_le16(ring_attr->flags); + req.enables = 0; + req.page_tbl_addr = cpu_to_le64(ring_attr->dma_arr[0]); + if (ring_attr->pages > 1) { + /* Page size is in log2 units */ + req.page_size = BNXT_PAGE_SHIFT; + req.page_tbl_depth = 1; + } else { + req.page_size = 4; + req.page_tbl_depth = 0; + } + + req.fbo = 0; + /* Association of ring index with doorbell index and MSIX number */ + req.logical_id = cpu_to_le16(ring_attr->lrid); + req.length = cpu_to_le32(ring_attr->depth + 1); + req.ring_type = ring_attr->type; + req.int_mode = ring_attr->mode; + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to allocate HW ring with rc = 0x%x", rc); + return rc; + } + *fw_ring_id = le16_to_cpu(resp.ring_id); + dev_dbg(rdev_to_dev(rdev), + "HW ring allocated with id = 0x%x at slot 0x%x", + resp.ring_id, ring_attr->lrid); + + return rc; +} + +static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev, + u32 fw_stats_ctx_id, u16 tid) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_stat_ctx_free_input req = {0}; + struct hwrm_stat_ctx_free_output resp; + struct bnxt_fw_msg fw_msg; + int rc = -EINVAL; + + if (!en_dev) + return rc; + + /* To avoid unnecessary error messages during recovery. + * HW is anyway in error state. So dont send down the command */ + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + return 0; + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_FREE, -1, tid); + req.stat_ctx_id = cpu_to_le32(fw_stats_ctx_id); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to free HW stats ctx with rc = 0x%x", rc); + return rc; + } + dev_dbg(rdev_to_dev(rdev), + "HW stats ctx freed with id = 0x%x", fw_stats_ctx_id); + + return rc; +} + +static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev, u16 tid) +{ + struct hwrm_stat_ctx_alloc_output resp = {}; + struct hwrm_stat_ctx_alloc_input req = {}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_qplib_stats *stat; + struct bnxt_qplib_ctx *hctx; + struct bnxt_fw_msg fw_msg; + int rc = 0; + + hctx = rdev->qplib_res.hctx; + stat = (tid == 0xffff) ? &hctx->stats : &hctx->stats2; + stat->fw_id = INVALID_STATS_CTX_ID; + + if (!en_dev) + return -EINVAL; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_STAT_CTX_ALLOC, -1, tid); + req.update_period_ms = cpu_to_le32(1000); + req.stats_dma_length = rdev->chip_ctx->hw_stats_size; + req.stats_dma_addr = cpu_to_le64(stat->dma_map); + req.stat_ctx_flags = HWRM_STAT_CTX_ALLOC_INPUT_STAT_CTX_FLAGS_ROCE; + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to allocate HW stats ctx, rc = 0x%x", rc); + return rc; + } + stat->fw_id = le32_to_cpu(resp.stat_ctx_id); + dev_dbg(rdev_to_dev(rdev), "HW stats ctx allocated with id = 0x%x", + stat->fw_id); + + return rc; +} + +static void bnxt_re_net_unregister_async_event(struct bnxt_re_dev *rdev) +{ + const struct bnxt_en_ops *en_ops; + + if (rdev->is_virtfn || + test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + return; + + memset(rdev->event_bitmap, 0, sizeof(rdev->event_bitmap)); + en_ops = rdev->en_dev->en_ops; + if (en_ops->bnxt_register_fw_async_events + (rdev->en_dev, BNXT_ROCE_ULP, + (unsigned long *)rdev->event_bitmap, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_NQ_UPDATE)) + dev_err(rdev_to_dev(rdev), + "Failed to unregister async event"); +} + +static void bnxt_re_net_register_async_event(struct bnxt_re_dev *rdev) +{ + const struct bnxt_en_ops *en_ops; + + if (rdev->is_virtfn) + return; + + rdev->event_bitmap[0] |= + BIT(HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE) | + BIT(HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY); + + rdev->event_bitmap[2] |= + BIT(HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT - 64); + rdev->event_bitmap[2] |= + BIT(HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_THRESHOLD - 64) | + BIT(HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_NQ_UPDATE - 64); + en_ops = rdev->en_dev->en_ops; + if (en_ops->bnxt_register_fw_async_events + (rdev->en_dev, BNXT_ROCE_ULP, + (unsigned long *)rdev->event_bitmap, + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DOORBELL_PACING_NQ_UPDATE)) + dev_err(rdev_to_dev(rdev), + "Failed to reg Async event"); +} + +static int bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_ver_get_output resp = {0}; + struct hwrm_ver_get_input req = {0}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_fw_msg fw_msg; + int rc = 0; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_VER_GET, -1, -1); + req.hwrm_intf_maj = HWRM_VERSION_MAJOR; + req.hwrm_intf_min = HWRM_VERSION_MINOR; + req.hwrm_intf_upd = HWRM_VERSION_UPDATE; + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query HW version, rc = 0x%x", rc); + return rc; + } + cctx = rdev->chip_ctx; + cctx->hwrm_intf_ver = (u64) le16_to_cpu(resp.hwrm_intf_major) << 48 | + (u64) le16_to_cpu(resp.hwrm_intf_minor) << 32 | + (u64) le16_to_cpu(resp.hwrm_intf_build) << 16 | + le16_to_cpu(resp.hwrm_intf_patch); + + cctx->hwrm_cmd_max_timeout = le16_to_cpu(resp.max_req_timeout); + + if (!cctx->hwrm_cmd_max_timeout) + cctx->hwrm_cmd_max_timeout = RCFW_FW_STALL_MAX_TIMEOUT; + + cctx->chip_num = le16_to_cpu(resp.chip_num); + cctx->chip_rev = resp.chip_rev; + cctx->chip_metal = resp.chip_metal; + return 0; +} + +/* Query device config using common hwrm */ +static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len, + u32 *offset) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_func_qcfg_output resp = {0}; + struct hwrm_func_qcfg_input req = {0}; + struct bnxt_fw_msg fw_msg; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_QCFG, -1, -1); + req.fid = cpu_to_le16(0xffff); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query config, rc = %#x", rc); + return rc; + } + + *db_len = PAGE_ALIGN(le16_to_cpu(resp.l2_doorbell_bar_size_kb) * 1024); + *offset = PAGE_ALIGN(le16_to_cpu(resp.legacy_l2_db_size_kb) * 1024); + return 0; +} + +/* Query function capabilities using common hwrm */ +int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_func_qcaps_output resp = {0}; + struct hwrm_func_qcaps_input req = {0}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_fw_msg fw_msg; + u8 push_enable = false; + int rc; + + cctx = rdev->chip_ctx; + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_QCAPS, -1, -1); + req.fid = cpu_to_le16(0xffff); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query capabilities, rc = %#x", rc); + return rc; + } + if (_is_chip_p7(rdev->chip_ctx)) + push_enable = + (resp.flags_ext & + HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PPP_PUSH_MODE_SUPPORTED) ? + true : false; + else + push_enable = + (resp.flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WCB_PUSH_MODE) ? + true : false; + cctx->modes.db_push = push_enable; + + cctx->modes.dbr_pacing = + resp.flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_DBR_PACING_SUPPORTED ? + true : false; + cctx->modes.dbr_pacing_ext = + resp.flags_ext2 & + HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DBR_PACING_EXT_SUPPORTED ? + true : false; + cctx->modes.dbr_drop_recov = + (resp.flags_ext2 & + HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_DBR_DROP_RECOVERY_SUPPORTED) ? + true : false; + cctx->modes.dbr_pacing_v0 = + (resp.flags_ext2 & + HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DBR_PACING_V0_SUPPORTED) ? + true : false; + dev_dbg(rdev_to_dev(rdev), + "%s: cctx->modes.dbr_pacing = %d cctx->modes.dbr_pacing_ext = %d, dbr_drop_recov %d\n", + __func__, cctx->modes.dbr_pacing, cctx->modes.dbr_pacing_ext, cctx->modes.dbr_drop_recov); + + return 0; +} + +static int bnxt_re_hwrm_dbr_pacing_qcfg(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data; + struct hwrm_func_dbr_pacing_qcfg_output resp = {0}; + struct hwrm_func_dbr_pacing_qcfg_input req = {0}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_fw_msg fw_msg; + u32 primary_nq_id; + int rc; + + cctx = rdev->chip_ctx; + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_DBR_PACING_QCFG, -1, -1); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_dbg(rdev_to_dev(rdev), + "Failed to query dbr pacing config, rc = %#x", rc); + return rc; + } + + primary_nq_id = le32_to_cpu(resp.primary_nq_id); + if (primary_nq_id == 0xffffffff && + !bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { + dev_err(rdev_to_dev(rdev), "%s:%d Invoke bnxt_qplib_dbr_pacing_set_primary_pf with 1\n", + __func__, __LINE__); + bnxt_qplib_dbr_pacing_set_primary_pf(rdev->chip_ctx, 1); + } + + if (bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { + struct bnxt_qplib_nq *nq; + + nq = &rdev->nqr.nq[0]; + /* Reset the primary capability */ + if (nq->ring_id != primary_nq_id) + bnxt_qplib_dbr_pacing_set_primary_pf(rdev->chip_ctx, 0); + } + + if ((resp.dbr_stat_db_fifo_reg & + HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_MASK) == + HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_GRC) + cctx->dbr_stat_db_fifo = + resp.dbr_stat_db_fifo_reg & + ~HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_MASK; + + if ((resp.dbr_throttling_aeq_arm_reg & + HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_MASK) + == HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_GRC) { + cctx->dbr_aeq_arm_reg = resp.dbr_throttling_aeq_arm_reg & + ~HWRM_FUNC_DBR_PACING_QCFG_OUTPUT_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_MASK; + cctx->dbr_throttling_reg = cctx->dbr_aeq_arm_reg - 4; + } + pacing_data->fifo_max_depth = le32_to_cpu(resp.dbr_stat_db_max_fifo_depth); + if (!pacing_data->fifo_max_depth) + pacing_data->fifo_max_depth = BNXT_RE_MAX_FIFO_DEPTH(cctx); + pacing_data->fifo_room_mask = le32_to_cpu(resp.dbr_stat_db_fifo_reg_fifo_room_mask); + pacing_data->fifo_room_shift = resp.dbr_stat_db_fifo_reg_fifo_room_shift; + dev_dbg(rdev_to_dev(rdev), + "%s: nq:0x%x primary_pf:%d db_fifo:0x%x aeq_arm:0x%x i" + "fifo_max_depth 0x%x , resp.dbr_stat_db_max_fifo_depth 0x%x);\n", + __func__, resp.primary_nq_id, cctx->modes.dbr_primary_pf, + cctx->dbr_stat_db_fifo, cctx->dbr_aeq_arm_reg, + pacing_data->fifo_max_depth, + le32_to_cpu(resp.dbr_stat_db_max_fifo_depth)); + return 0; +} + +static int bnxt_re_hwrm_dbr_pacing_cfg(struct bnxt_re_dev *rdev, bool enable) +{ + struct hwrm_func_dbr_pacing_cfg_output resp = {0}; + struct hwrm_func_dbr_pacing_cfg_input req = {0}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + int rc; + + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + return 0; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_DBR_PACING_CFG, -1, -1); + if (enable) { + req.flags = HWRM_FUNC_DBR_PACING_CFG_INPUT_FLAGS_DBR_NQ_EVENT_ENABLE; + req.enables = + cpu_to_le32(HWRM_FUNC_DBR_PACING_CFG_INPUT_ENABLES_PRIMARY_NQ_ID_VALID | + HWRM_FUNC_DBR_PACING_CFG_INPUT_ENABLES_PACING_THRESHOLD_VALID); + } else { + req.flags = HWRM_FUNC_DBR_PACING_CFG_INPUT_FLAGS_DBR_NQ_EVENT_DISABLE; + } + req.primary_nq_id = cpu_to_le32(rdev->dbq_nq_id); + req.pacing_threshold = cpu_to_le32(rdev->dbq_watermark); + dev_dbg(rdev_to_dev(rdev), "%s: nq_id = 0x%x pacing_threshold = 0x%x", + __func__, req.primary_nq_id, req.pacing_threshold); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_dbg(rdev_to_dev(rdev), + "Failed to set dbr pacing config, rc = %#x", rc); + return rc; + } + return 0; +} + +/* Net -> RoCE driver */ + +/* Device */ +struct bnxt_re_dev *bnxt_re_from_netdev(struct ifnet *netdev) +{ + struct bnxt_re_dev *rdev; + + rcu_read_lock(); + list_for_each_entry_rcu(rdev, &bnxt_re_dev_list, list) { + if (rdev->netdev == netdev) { + rcu_read_unlock(); + dev_dbg(rdev_to_dev(rdev), + "netdev (%p) found, ref_count = 0x%x", + netdev, atomic_read(&rdev->ref_count)); + return rdev; + } + } + rcu_read_unlock(); + return NULL; +} + +static ssize_t show_rev(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(device, ibdev.dev); + + return scnprintf(buf, PAGE_SIZE, "0x%x\n", rdev->en_dev->pdev->vendor); +} + + +static ssize_t show_hca(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(device, ibdev.dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", rdev->ibdev.node_desc); +} + +static DEVICE_ATTR(hw_rev, 0444, show_rev, NULL); +static DEVICE_ATTR(hca_type, 0444, show_hca, NULL); +static struct device_attribute *bnxt_re_attributes[] = { + &dev_attr_hw_rev, + &dev_attr_hca_type +}; + +int ib_register_device_compat(struct bnxt_re_dev *rdev) +{ + struct ib_device *ibdev = &rdev->ibdev; + char name[IB_DEVICE_NAME_MAX]; + + memset(name, 0, IB_DEVICE_NAME_MAX); + strlcpy(name, "bnxt_re%d", IB_DEVICE_NAME_MAX); + + strlcpy(ibdev->name, name, IB_DEVICE_NAME_MAX); + + return ib_register_device(ibdev, NULL); +} + +static int bnxt_re_register_ib(struct bnxt_re_dev *rdev) +{ + struct ib_device *ibdev = &rdev->ibdev; + int ret = 0; + + /* ib device init */ + ibdev->owner = THIS_MODULE; + ibdev->uverbs_abi_ver = BNXT_RE_ABI_VERSION; + ibdev->node_type = RDMA_NODE_IB_CA; + strlcpy(ibdev->node_desc, BNXT_RE_DESC " HCA", + strlen(BNXT_RE_DESC) + 5); + ibdev->phys_port_cnt = 1; + + bnxt_qplib_get_guid(rdev->dev_addr, (u8 *)&ibdev->node_guid); + + /* Data path irqs is one less than the max msix vectors */ + ibdev->num_comp_vectors = rdev->nqr.num_msix - 1; + bnxt_re_set_dma_device(ibdev, rdev); + ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY; + + /* User space */ + ibdev->uverbs_cmd_mask = + (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | + (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | + (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | + (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | + (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | + (1ull << IB_USER_VERBS_CMD_REG_MR) | + (1ull << IB_USER_VERBS_CMD_DEREG_MR) | + (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | + (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | + (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | + (1ull << IB_USER_VERBS_CMD_CREATE_QP) | + (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | + (1ull << IB_USER_VERBS_CMD_QUERY_QP) | + (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | + (1ull << IB_USER_VERBS_CMD_REREG_MR) | + (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | + (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | + (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | + (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | + (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) | + (1ull << IB_USER_VERBS_CMD_ALLOC_MW) | + (1ull << IB_USER_VERBS_CMD_DEALLOC_MW) | + (1ull << IB_USER_VERBS_CMD_CREATE_AH) | + (1ull << IB_USER_VERBS_CMD_MODIFY_AH) | + (1ull << IB_USER_VERBS_CMD_QUERY_AH) | + (1ull << IB_USER_VERBS_CMD_DESTROY_AH); + + ibdev->uverbs_ex_cmd_mask = (1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP); + ibdev->uverbs_cmd_mask |= (1ull << IB_USER_VERBS_CMD_POLL_CQ); + +#define bnxt_re_ib_ah bnxt_re_ah +#define bnxt_re_ib_cq bnxt_re_cq +#define bnxt_re_ib_pd bnxt_re_pd +#define bnxt_re_ib_srq bnxt_re_srq +#define bnxt_re_ib_ucontext bnxt_re_ucontext + INIT_IB_DEVICE_OPS(&ibdev->ops, bnxt_re, BNXT_RE); + + ibdev->query_device = bnxt_re_query_device; + ibdev->modify_device = bnxt_re_modify_device; + ibdev->query_port = bnxt_re_query_port; + ibdev->modify_port = bnxt_re_modify_port; + ibdev->get_port_immutable = bnxt_re_get_port_immutable; + ibdev->query_pkey = bnxt_re_query_pkey; + ibdev->query_gid = bnxt_re_query_gid; + ibdev->get_netdev = bnxt_re_get_netdev; + ibdev->add_gid = bnxt_re_add_gid; + ibdev->del_gid = bnxt_re_del_gid; + ibdev->get_link_layer = bnxt_re_get_link_layer; + ibdev->alloc_pd = bnxt_re_alloc_pd; + ibdev->dealloc_pd = bnxt_re_dealloc_pd; + ibdev->create_ah = bnxt_re_create_ah; + ibdev->modify_ah = bnxt_re_modify_ah; + ibdev->query_ah = bnxt_re_query_ah; + ibdev->destroy_ah = bnxt_re_destroy_ah; + ibdev->create_srq = bnxt_re_create_srq; + ibdev->modify_srq = bnxt_re_modify_srq; + ibdev->query_srq = bnxt_re_query_srq; + ibdev->destroy_srq = bnxt_re_destroy_srq; + ibdev->post_srq_recv = bnxt_re_post_srq_recv; + ibdev->create_qp = bnxt_re_create_qp; + ibdev->modify_qp = bnxt_re_modify_qp; + ibdev->query_qp = bnxt_re_query_qp; + ibdev->destroy_qp = bnxt_re_destroy_qp; + ibdev->post_send = bnxt_re_post_send; + ibdev->post_recv = bnxt_re_post_recv; + ibdev->create_cq = bnxt_re_create_cq; + ibdev->modify_cq = bnxt_re_modify_cq; + ibdev->destroy_cq = bnxt_re_destroy_cq; + ibdev->resize_cq = bnxt_re_resize_cq; + ibdev->poll_cq = bnxt_re_poll_cq; + ibdev->req_notify_cq = bnxt_re_req_notify_cq; + ibdev->get_dma_mr = bnxt_re_get_dma_mr; + ibdev->get_hw_stats = bnxt_re_get_hw_stats; + ibdev->alloc_hw_stats = bnxt_re_alloc_hw_port_stats; + ibdev->dereg_mr = bnxt_re_dereg_mr; + ibdev->alloc_mr = bnxt_re_alloc_mr; + ibdev->map_mr_sg = bnxt_re_map_mr_sg; + ibdev->alloc_mw = bnxt_re_alloc_mw; + ibdev->dealloc_mw = bnxt_re_dealloc_mw; + ibdev->reg_user_mr = bnxt_re_reg_user_mr; + ibdev->rereg_user_mr = bnxt_re_rereg_user_mr; + ibdev->disassociate_ucontext = bnxt_re_disassociate_ucntx; + ibdev->alloc_ucontext = bnxt_re_alloc_ucontext; + ibdev->dealloc_ucontext = bnxt_re_dealloc_ucontext; + ibdev->mmap = bnxt_re_mmap; + ibdev->process_mad = bnxt_re_process_mad; + + ret = ib_register_device_compat(rdev); + return ret; +} + +static void bnxt_re_dev_dealloc(struct bnxt_re_dev *rdev) +{ + int i = BNXT_RE_REF_WAIT_COUNT; + + dev_dbg(rdev_to_dev(rdev), "%s:Remove the device %p\n", __func__, rdev); + /* Wait for rdev refcount to come down */ + while ((atomic_read(&rdev->ref_count) > 1) && i--) + msleep(100); + + if (atomic_read(&rdev->ref_count) > 1) + dev_err(rdev_to_dev(rdev), + "Failed waiting for ref count to deplete %d", + atomic_read(&rdev->ref_count)); + + atomic_set(&rdev->ref_count, 0); + if_rele(rdev->netdev); + rdev->netdev = NULL; + synchronize_rcu(); + + kfree(rdev->gid_map); + kfree(rdev->dbg_stats); + ib_dealloc_device(&rdev->ibdev); +} + +static struct bnxt_re_dev *bnxt_re_dev_alloc(struct ifnet *netdev, + struct bnxt_en_dev *en_dev) +{ + struct bnxt_re_dev *rdev; + u32 count; + + /* Allocate bnxt_re_dev instance here */ + rdev = (struct bnxt_re_dev *)compat_ib_alloc_device(sizeof(*rdev)); + if (!rdev) { + pr_err("%s: bnxt_re_dev allocation failure!", + ROCE_DRV_MODULE_NAME); + return NULL; + } + /* Default values */ + atomic_set(&rdev->ref_count, 0); + rdev->netdev = netdev; + dev_hold(rdev->netdev); + rdev->en_dev = en_dev; + rdev->id = rdev->en_dev->pdev->devfn; + INIT_LIST_HEAD(&rdev->qp_list); + mutex_init(&rdev->qp_lock); + mutex_init(&rdev->cc_lock); + mutex_init(&rdev->dbq_lock); + bnxt_re_clear_rsors_stat(&rdev->stats.rsors); + rdev->cosq[0] = rdev->cosq[1] = 0xFFFF; + rdev->min_tx_depth = 1; + rdev->stats.stats_query_sec = 1; + /* Disable priority vlan as the default mode is DSCP based PFC */ + rdev->cc_param.disable_prio_vlan_tx = 1; + + /* Initialize worker for DBR Pacing */ + INIT_WORK(&rdev->dbq_fifo_check_work, bnxt_re_db_fifo_check); + INIT_DELAYED_WORK(&rdev->dbq_pacing_work, bnxt_re_pacing_timer_exp); + rdev->gid_map = kzalloc(sizeof(*(rdev->gid_map)) * + BNXT_RE_MAX_SGID_ENTRIES, + GFP_KERNEL); + if (!rdev->gid_map) { + ib_dealloc_device(&rdev->ibdev); + return NULL; + } + for(count = 0; count < BNXT_RE_MAX_SGID_ENTRIES; count++) + rdev->gid_map[count] = -1; + + rdev->dbg_stats = kzalloc(sizeof(*rdev->dbg_stats), GFP_KERNEL); + if (!rdev->dbg_stats) { + ib_dealloc_device(&rdev->ibdev); + return NULL; + } + + return rdev; +} + +static int bnxt_re_handle_unaffi_async_event( + struct creq_func_event *unaffi_async) +{ + switch (unaffi_async->event) { + case CREQ_FUNC_EVENT_EVENT_TX_WQE_ERROR: + case CREQ_FUNC_EVENT_EVENT_TX_DATA_ERROR: + case CREQ_FUNC_EVENT_EVENT_RX_WQE_ERROR: + case CREQ_FUNC_EVENT_EVENT_RX_DATA_ERROR: + case CREQ_FUNC_EVENT_EVENT_CQ_ERROR: + case CREQ_FUNC_EVENT_EVENT_TQM_ERROR: + case CREQ_FUNC_EVENT_EVENT_CFCQ_ERROR: + case CREQ_FUNC_EVENT_EVENT_CFCS_ERROR: + case CREQ_FUNC_EVENT_EVENT_CFCC_ERROR: + case CREQ_FUNC_EVENT_EVENT_CFCM_ERROR: + case CREQ_FUNC_EVENT_EVENT_TIM_ERROR: + break; + default: + return -EINVAL; + } + return 0; +} + +static int bnxt_re_handle_qp_async_event(void *qp_event, struct bnxt_re_qp *qp) +{ + struct creq_qp_error_notification *err_event; + struct ib_event event; + unsigned int flags; + + if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR && + !qp->qplib_qp.is_user) { + flags = bnxt_re_lock_cqs(qp); + bnxt_qplib_add_flush_qp(&qp->qplib_qp); + bnxt_re_unlock_cqs(qp, flags); + } + memset(&event, 0, sizeof(event)); + event.device = &qp->rdev->ibdev; + event.element.qp = &qp->ib_qp; + event.event = IB_EVENT_QP_FATAL; + + err_event = qp_event; + switch(err_event->res_err_state_reason) { + case CFCQ_RES_ERR_STATE_REASON_RES_EXCEED_MAX: + case CFCQ_RES_ERR_STATE_REASON_RES_PAYLOAD_LENGTH_MISMATCH: + case CFCQ_RES_ERR_STATE_REASON_RES_OPCODE_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_PSN_SEQ_ERROR_RETRY_LIMIT: + case CFCQ_RES_ERR_STATE_REASON_RES_RX_INVALID_R_KEY: + case CFCQ_RES_ERR_STATE_REASON_RES_RX_DOMAIN_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_RX_NO_PERMISSION: + case CFCQ_RES_ERR_STATE_REASON_RES_RX_RANGE_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_TX_INVALID_R_KEY: + case CFCQ_RES_ERR_STATE_REASON_RES_TX_DOMAIN_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_TX_NO_PERMISSION: + case CFCQ_RES_ERR_STATE_REASON_RES_TX_RANGE_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_IVALID_DUP_RKEY: + case CFCQ_RES_ERR_STATE_REASON_RES_UNALIGN_ATOMIC: + event.event = IB_EVENT_QP_ACCESS_ERR; + break; + case CFCQ_RES_ERR_STATE_REASON_RES_EXCEEDS_WQE: + case CFCQ_RES_ERR_STATE_REASON_RES_WQE_FORMAT_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_SRQ_LOAD_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_UNSUPPORTED_OPCODE: + case CFCQ_RES_ERR_STATE_REASON_RES_REM_INVALIDATE: + event.event = IB_EVENT_QP_REQ_ERR; + break; + case CFCQ_RES_ERR_STATE_REASON_RES_IRRQ_OFLOW: + case CFCQ_RES_ERR_STATE_REASON_RES_CMP_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_CQ_LOAD_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_TX_PCI_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_RX_PCI_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_MEMORY_ERROR: + case CFCQ_RES_ERR_STATE_REASON_RES_SRQ_ERROR: + event.event = IB_EVENT_QP_FATAL; + break; + default: + if (qp->qplib_qp.srq) + event.event = IB_EVENT_QP_LAST_WQE_REACHED; + break; + } + + if (err_event->res_err_state_reason) + dev_err(rdev_to_dev(qp->rdev), + "%s %s qp_id: %d cons (%d %d) req (%d %d) res (%d %d)\n", + __func__, qp->qplib_qp.is_user ? "user" : "kernel", + qp->qplib_qp.id, + err_event->sq_cons_idx, + err_event->rq_cons_idx, + err_event->req_slow_path_state, + err_event->req_err_state_reason, + err_event->res_slow_path_state, + err_event->res_err_state_reason); + + if (event.device && qp->ib_qp.event_handler) + qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context); + + return 0; +} + +static int bnxt_re_handle_cq_async_error(void *event, struct bnxt_re_cq *cq) +{ + struct creq_cq_error_notification *cqerr; + bool send = false; + + cqerr = event; + switch (cqerr->cq_err_reason) { + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_REQ_CQ_INVALID_ERROR: + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_REQ_CQ_OVERFLOW_ERROR: + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_REQ_CQ_LOAD_ERROR: + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_RES_CQ_INVALID_ERROR: + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_RES_CQ_OVERFLOW_ERROR: + case CREQ_CQ_ERROR_NOTIFICATION_CQ_ERR_REASON_RES_CQ_LOAD_ERROR: + send = true; + default: + break; + } + + if (send && cq->ibcq.event_handler) { + struct ib_event ibevent = {}; + + ibevent.event = IB_EVENT_CQ_ERR; + ibevent.element.cq = &cq->ibcq; + ibevent.device = &cq->rdev->ibdev; + + dev_err(rdev_to_dev(cq->rdev), + "%s err reason %d\n", __func__, cqerr->cq_err_reason); + cq->ibcq.event_handler(&ibevent, cq->ibcq.cq_context); + } + + cq->qplib_cq.is_cq_err_event = true; + + return 0; +} + +static int bnxt_re_handle_affi_async_event(struct creq_qp_event *affi_async, + void *obj) +{ + struct bnxt_qplib_qp *qplqp; + struct bnxt_qplib_cq *qplcq; + struct bnxt_re_qp *qp; + struct bnxt_re_cq *cq; + int rc = 0; + u8 event; + + if (!obj) + return rc; /* QP was already dead, still return success */ + + event = affi_async->event; + switch (event) { + case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION: + qplqp = obj; + qp = container_of(qplqp, struct bnxt_re_qp, qplib_qp); + rc = bnxt_re_handle_qp_async_event(affi_async, qp); + break; + case CREQ_QP_EVENT_EVENT_CQ_ERROR_NOTIFICATION: + qplcq = obj; + cq = container_of(qplcq, struct bnxt_re_cq, qplib_cq); + rc = bnxt_re_handle_cq_async_error(affi_async, cq); + break; + default: + rc = -EINVAL; + } + + return rc; +} + +static int bnxt_re_aeq_handler(struct bnxt_qplib_rcfw *rcfw, + void *aeqe, void *obj) +{ + struct creq_func_event *unaffi_async; + struct creq_qp_event *affi_async; + u8 type; + int rc; + + type = ((struct creq_base *)aeqe)->type; + if (type == CREQ_BASE_TYPE_FUNC_EVENT) { + unaffi_async = aeqe; + rc = bnxt_re_handle_unaffi_async_event(unaffi_async); + } else { + affi_async = aeqe; + rc = bnxt_re_handle_affi_async_event(affi_async, obj); + } + + return rc; +} + +static int bnxt_re_srqn_handler(struct bnxt_qplib_nq *nq, + struct bnxt_qplib_srq *handle, u8 event) +{ + struct bnxt_re_srq *srq = to_bnxt_re(handle, struct bnxt_re_srq, + qplib_srq); + struct ib_event ib_event; + + if (srq == NULL) { + pr_err("%s: SRQ is NULL, SRQN not handled", + ROCE_DRV_MODULE_NAME); + return -EINVAL; + } + ib_event.device = &srq->rdev->ibdev; + ib_event.element.srq = &srq->ibsrq; + if (event == NQ_SRQ_EVENT_EVENT_SRQ_THRESHOLD_EVENT) + ib_event.event = IB_EVENT_SRQ_LIMIT_REACHED; + else + ib_event.event = IB_EVENT_SRQ_ERR; + + if (srq->ibsrq.event_handler) { + /* Lock event_handler? */ + (*srq->ibsrq.event_handler)(&ib_event, + srq->ibsrq.srq_context); + } + return 0; +} + +static int bnxt_re_cqn_handler(struct bnxt_qplib_nq *nq, + struct bnxt_qplib_cq *handle) +{ + struct bnxt_re_cq *cq = to_bnxt_re(handle, struct bnxt_re_cq, + qplib_cq); + u32 *cq_ptr; + + if (cq == NULL) { + pr_err("%s: CQ is NULL, CQN not handled", + ROCE_DRV_MODULE_NAME); + return -EINVAL; + } + /* CQ already in destroy path. Do not handle any more events */ + if (handle->destroyed || !atomic_read(&cq->ibcq.usecnt)) { + if (!handle->destroyed) + dev_dbg(NULL, "%s: CQ being destroyed, CQN not handled", + ROCE_DRV_MODULE_NAME); + return 0; + } + + if (cq->ibcq.comp_handler) { + if (cq->uctx_cq_page) { + cq_ptr = (u32 *)cq->uctx_cq_page; + *cq_ptr = cq->qplib_cq.toggle; + } + /* Lock comp_handler? */ + (*cq->ibcq.comp_handler)(&cq->ibcq, cq->ibcq.cq_context); + } + + return 0; +} + +struct bnxt_qplib_nq *bnxt_re_get_nq(struct bnxt_re_dev *rdev) +{ + int min, indx; + + mutex_lock(&rdev->nqr.load_lock); + for (indx = 0, min = 0; indx < (rdev->nqr.num_msix - 1); indx++) { + if (rdev->nqr.nq[min].load > rdev->nqr.nq[indx].load) + min = indx; + } + rdev->nqr.nq[min].load++; + mutex_unlock(&rdev->nqr.load_lock); + + return &rdev->nqr.nq[min]; +} + +void bnxt_re_put_nq(struct bnxt_re_dev *rdev, struct bnxt_qplib_nq *nq) +{ + mutex_lock(&rdev->nqr.load_lock); + nq->load--; + mutex_unlock(&rdev->nqr.load_lock); +} + +static bool bnxt_re_check_min_attr(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_dev_attr *attr; + bool rc = true; + + attr = rdev->dev_attr; + + if (!attr->max_cq || !attr->max_qp || + !attr->max_sgid || !attr->max_mr) { + dev_err(rdev_to_dev(rdev),"Insufficient RoCE resources"); + dev_dbg(rdev_to_dev(rdev), + "max_cq = %d, max_qp = %d, max_dpi = %d, max_sgid = %d, max_mr = %d", + attr->max_cq, attr->max_qp, attr->max_dpi, + attr->max_sgid, attr->max_mr); + rc = false; + } + return rc; +} + +static void bnxt_re_dispatch_event(struct ib_device *ibdev, struct ib_qp *qp, + u8 port_num, enum ib_event_type event) +{ + struct ib_event ib_event; + + ib_event.device = ibdev; + if (qp) { + ib_event.element.qp = qp; + ib_event.event = event; + if (qp->event_handler) + qp->event_handler(&ib_event, qp->qp_context); + } else { + ib_event.element.port_num = port_num; + ib_event.event = event; + ib_dispatch_event(&ib_event); + } + + dev_dbg(rdev_to_dev(to_bnxt_re_dev(ibdev, ibdev)), + "ibdev %p Event 0x%x port_num 0x%x", ibdev, event, port_num); +} + +static bool bnxt_re_is_qp1_or_shadow_qp(struct bnxt_re_dev *rdev, + struct bnxt_re_qp *qp) +{ + if (rdev->gsi_ctx.gsi_qp_mode == BNXT_RE_GSI_MODE_ALL) + return (qp->ib_qp.qp_type == IB_QPT_GSI) || + (qp == rdev->gsi_ctx.gsi_sqp); + else + return (qp->ib_qp.qp_type == IB_QPT_GSI); +} + +static void bnxt_re_stop_all_nonqp1_nonshadow_qps(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_qp *qpl_qp; + bool dev_detached = false; + struct ib_qp_attr qp_attr; + int num_qps_stopped = 0; + int mask = IB_QP_STATE; + struct bnxt_re_qp *qp; + unsigned long flags; + + if (!rdev) + return; + +restart: + if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) + dev_detached = true; + + qp_attr.qp_state = IB_QPS_ERR; + mutex_lock(&rdev->qp_lock); + list_for_each_entry(qp, &rdev->qp_list, list) { + qpl_qp = &qp->qplib_qp; + if (dev_detached || !bnxt_re_is_qp1_or_shadow_qp(rdev, qp)) { + if (qpl_qp->state != + CMDQ_MODIFY_QP_NEW_STATE_RESET && + qpl_qp->state != + CMDQ_MODIFY_QP_NEW_STATE_ERR) { + if (dev_detached) { + /* + * Cant actually send the command down, + * marking the state for bookkeeping + */ + qpl_qp->state = + CMDQ_MODIFY_QP_NEW_STATE_ERR; + qpl_qp->cur_qp_state = qpl_qp->state; + if (!qpl_qp->is_user) { + /* Add to flush list */ + flags = bnxt_re_lock_cqs(qp); + bnxt_qplib_add_flush_qp(qpl_qp); + bnxt_re_unlock_cqs(qp, flags); + } + } else { + num_qps_stopped++; + bnxt_re_modify_qp(&qp->ib_qp, + &qp_attr, mask, + NULL); + } + + bnxt_re_dispatch_event(&rdev->ibdev, &qp->ib_qp, + 1, IB_EVENT_QP_FATAL); + /* + * 1. Release qp_lock after a budget to unblock other verb + * requests (like qp_destroy) from stack. + * 2. Traverse through the qp_list freshly as addition / deletion + * might have happened since qp_lock is getting released here. + */ + if (num_qps_stopped % BNXT_RE_STOP_QPS_BUDGET == 0) { + mutex_unlock(&rdev->qp_lock); + goto restart; + } + } + } + } + + mutex_unlock(&rdev->qp_lock); +} + +static int bnxt_re_update_gid(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; + struct bnxt_qplib_gid gid; + u16 gid_idx, index; + int rc = 0; + + if (!test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) + return 0; + + if (sgid_tbl == NULL) { + dev_err(rdev_to_dev(rdev), "QPLIB: SGID table not allocated"); + return -EINVAL; + } + + for (index = 0; index < sgid_tbl->active; index++) { + gid_idx = sgid_tbl->hw_id[index]; + + if (!memcmp(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, + sizeof(bnxt_qplib_gid_zero))) + continue; + /* Need to modify the VLAN enable setting of non VLAN GID only + * as setting is done for VLAN GID while adding GID + * + * If disable_prio_vlan_tx is enable, then we'll need to remove the + * vlan entry from the sgid_tbl. + */ + if (sgid_tbl->vlan[index] == true) + continue; + + memcpy(&gid, &sgid_tbl->tbl[index], sizeof(gid)); + + rc = bnxt_qplib_update_sgid(sgid_tbl, &gid, gid_idx, + rdev->dev_addr); + } + + return rc; +} + +static void bnxt_re_clear_cc(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_cc_param *cc_param = &rdev->cc_param; + + if (_is_chip_p7(rdev->chip_ctx)) { + cc_param->mask = CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP; + } else { + cc_param->mask = (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN); + + if (!is_qport_service_type_supported(rdev)) + cc_param->mask |= + (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP); + } + + cc_param->cur_mask = cc_param->mask; + + if (bnxt_qplib_modify_cc(&rdev->qplib_res, cc_param)) + dev_err(rdev_to_dev(rdev), "Failed to modify cc\n"); +} + +static int bnxt_re_setup_cc(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_cc_param *cc_param = &rdev->cc_param; + int rc; + + if (_is_chip_p7(rdev->chip_ctx)) { + cc_param->enable = 0x0; + cc_param->mask = CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP; + } else { + cc_param->enable = 0x1; + cc_param->mask = (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN); + + if (!is_qport_service_type_supported(rdev)) + cc_param->mask |= + (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP | + CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP); + } + + cc_param->cur_mask = cc_param->mask; + + rc = bnxt_qplib_modify_cc(&rdev->qplib_res, cc_param); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to modify cc\n"); + return rc; + } + /* Reset the programming mask */ + cc_param->mask = 0; + if (cc_param->qp1_tos_dscp != cc_param->tos_dscp) { + cc_param->qp1_tos_dscp = cc_param->tos_dscp; + rc = bnxt_re_update_qp1_tos_dscp(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), "%s:Failed to modify QP1:%d", + __func__, rc); + goto clear; + } + } + return 0; + +clear: + bnxt_re_clear_cc(rdev); + return rc; +} + +int bnxt_re_query_hwrm_dscp2pri(struct bnxt_re_dev *rdev, + struct bnxt_re_dscp2pri *d2p, u16 *count, + u16 target_id) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_queue_dscp2pri_qcfg_input req; + struct hwrm_queue_dscp2pri_qcfg_output resp; + struct bnxt_re_dscp2pri *dscp2pri; + struct bnxt_fw_msg fw_msg; + u16 in_count = *count; + dma_addr_t dma_handle; + int rc = 0, i; + u16 data_len; + u8 *kmem; + + data_len = *count * sizeof(*dscp2pri); + memset(&fw_msg, 0, sizeof(fw_msg)); + memset(&req, 0, sizeof(req)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_QUEUE_DSCP2PRI_QCFG, -1, target_id); + req.port_id = (target_id == 0xFFFF) ? en_dev->pf_port_id : 1; + + kmem = dma_zalloc_coherent(&en_dev->pdev->dev, data_len, &dma_handle, + GFP_KERNEL); + if (!kmem) { + dev_err(rdev_to_dev(rdev), + "dma_zalloc_coherent failure, length = %u\n", + (unsigned)data_len); + return -ENOMEM; + } + req.dest_data_addr = cpu_to_le64(dma_handle); + req.dest_data_buffer_size = cpu_to_le16(data_len); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) + goto out; + + /* Upload the DSCP-MASK-PRI tuple(s) */ + dscp2pri = (struct bnxt_re_dscp2pri *)kmem; + for (i = 0; i < le16_to_cpu(resp.entry_cnt) && i < in_count; i++) { + d2p[i].dscp = dscp2pri->dscp; + d2p[i].mask = dscp2pri->mask; + d2p[i].pri = dscp2pri->pri; + dscp2pri++; + } + *count = le16_to_cpu(resp.entry_cnt); +out: + dma_free_coherent(&en_dev->pdev->dev, data_len, kmem, dma_handle); + return rc; +} + +int bnxt_re_prio_vlan_tx_update(struct bnxt_re_dev *rdev) +{ + /* Remove the VLAN from the GID entry */ + if (rdev->cc_param.disable_prio_vlan_tx) + rdev->qplib_res.prio = false; + else + rdev->qplib_res.prio = true; + + return bnxt_re_update_gid(rdev); +} + +int bnxt_re_set_hwrm_dscp2pri(struct bnxt_re_dev *rdev, + struct bnxt_re_dscp2pri *d2p, u16 count, + u16 target_id) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_queue_dscp2pri_cfg_input req; + struct hwrm_queue_dscp2pri_cfg_output resp; + struct bnxt_fw_msg fw_msg; + struct bnxt_re_dscp2pri *dscp2pri; + int i, rc, data_len = 3 * 256; + dma_addr_t dma_handle; + u8 *kmem; + + memset(&req, 0, sizeof(req)); + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_QUEUE_DSCP2PRI_CFG, -1, target_id); + req.port_id = (target_id == 0xFFFF) ? en_dev->pf_port_id : 1; + + kmem = dma_alloc_coherent(&en_dev->pdev->dev, data_len, &dma_handle, + GFP_KERNEL); + if (!kmem) { + dev_err(rdev_to_dev(rdev), + "dma_alloc_coherent failure, length = %u\n", + (unsigned)data_len); + return -ENOMEM; + } + req.src_data_addr = cpu_to_le64(dma_handle); + + /* Download the DSCP-MASK-PRI tuple(s) */ + dscp2pri = (struct bnxt_re_dscp2pri *)kmem; + for (i = 0; i < count; i++) { + dscp2pri->dscp = d2p[i].dscp; + dscp2pri->mask = d2p[i].mask; + dscp2pri->pri = d2p[i].pri; + dscp2pri++; + } + + req.entry_cnt = cpu_to_le16(count); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + dma_free_coherent(&en_dev->pdev->dev, data_len, kmem, dma_handle); + return rc; +} + +int bnxt_re_query_hwrm_qportcfg(struct bnxt_re_dev *rdev, + struct bnxt_re_tc_rec *tc_rec, u16 tid) +{ + u8 max_tc, tc, *qptr, *type_ptr0, *type_ptr1; + struct hwrm_queue_qportcfg_output resp = {0}; + struct hwrm_queue_qportcfg_input req = {0}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + bool def_init = false; + u8 *tmp_type; + u8 cos_id; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_QUEUE_QPORTCFG, + -1, tid); + req.port_id = (tid == 0xFFFF) ? en_dev->pf_port_id : 1; + if (BNXT_EN_ASYM_Q(en_dev)) + req.flags = htole32(HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX); + + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) + return rc; + + if (!resp.max_configurable_queues) + return -EINVAL; + + max_tc = resp.max_configurable_queues; + tc_rec->max_tc = max_tc; + + if (resp.queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_USE_PROFILE_TYPE) + tc_rec->serv_type_enabled = true; + + qptr = &resp.queue_id0; + type_ptr0 = &resp.queue_id0_service_profile_type; + type_ptr1 = &resp.queue_id1_service_profile_type; + for (tc = 0; tc < max_tc; tc++) { + tmp_type = tc ? type_ptr1 + (tc - 1) : type_ptr0; + + cos_id = *qptr++; + /* RoCE CoS queue is the first cos queue. + * For MP12 and MP17 order is 405 and 141015. + */ + if (is_bnxt_roce_queue(rdev, *qptr, *tmp_type)) { + tc_rec->cos_id_roce = cos_id; + tc_rec->tc_roce = tc; + } else if (is_bnxt_cnp_queue(rdev, *qptr, *tmp_type)) { + tc_rec->cos_id_cnp = cos_id; + tc_rec->tc_cnp = tc; + } else if (!def_init) { + def_init = true; + tc_rec->tc_def = tc; + tc_rec->cos_id_def = cos_id; + } + qptr++; + } + + return rc; +} + +int bnxt_re_hwrm_cos2bw_qcfg(struct bnxt_re_dev *rdev, u16 target_id, + struct bnxt_re_cos2bw_cfg *cfg) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_queue_cos2bw_qcfg_output resp; + struct hwrm_queue_cos2bw_qcfg_input req = {0}; + struct bnxt_fw_msg fw_msg; + int rc, indx; + void *data; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_QUEUE_COS2BW_QCFG, -1, target_id); + req.port_id = (target_id == 0xFFFF) ? en_dev->pf_port_id : 1; + + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) + return rc; + data = &resp.queue_id0 + offsetof(struct bnxt_re_cos2bw_cfg, + queue_id); + for (indx = 0; indx < 8; indx++, data += (sizeof(cfg->cfg))) { + memcpy(&cfg->cfg, data, sizeof(cfg->cfg)); + if (indx == 0) + cfg->queue_id = resp.queue_id0; + cfg++; + } + + return rc; +} + +int bnxt_re_hwrm_cos2bw_cfg(struct bnxt_re_dev *rdev, u16 target_id, + struct bnxt_re_cos2bw_cfg *cfg) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_queue_cos2bw_cfg_input req = {0}; + struct hwrm_queue_cos2bw_cfg_output resp = {0}; + struct bnxt_fw_msg fw_msg; + void *data; + int indx; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_QUEUE_COS2BW_CFG, -1, target_id); + req.port_id = (target_id == 0xFFFF) ? en_dev->pf_port_id : 1; + + /* Chimp wants enable bit to retain previous + * config done by L2 driver + */ + for (indx = 0; indx < 8; indx++) { + if (cfg[indx].queue_id < 40) { + req.enables |= cpu_to_le32( + HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID << + indx); + } + + data = (char *)&req.unused_0 + indx * (sizeof(*cfg) - 4); + memcpy(data, &cfg[indx].queue_id, sizeof(*cfg) - 4); + if (indx == 0) { + req.queue_id0 = cfg[0].queue_id; + req.unused_0 = 0; + } + } + + memset(&resp, 0, sizeof(resp)); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + return rc; +} + +int bnxt_re_host_pf_id_query(struct bnxt_re_dev *rdev, + struct bnxt_qplib_query_fn_info *fn_info, + u32 *pf_mask, u32 *first_pf) +{ + struct hwrm_func_host_pf_ids_query_output resp = {0}; + struct hwrm_func_host_pf_ids_query_input req; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + memset(&req, 0, sizeof(req)); + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, + HWRM_FUNC_HOST_PF_IDS_QUERY, -1, -1); + /* To query the info from the host EPs */ + switch (fn_info->host) { + case HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_SOC: + case HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_EP_0: + case HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_EP_1: + case HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_EP_2: + case HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_EP_3: + req.host = fn_info->host; + break; + default: + req.host = HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_HOST_EP_0; + break; + } + + req.filter = fn_info->filter; + if (req.filter > HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_FILTER_ROCE) + req.filter = HWRM_FUNC_HOST_PF_IDS_QUERY_INPUT_FILTER_ALL; + + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + + + *first_pf = le16_to_cpu(resp.first_pf_id); + *pf_mask = le16_to_cpu(resp.pf_ordinal_mask); + + return rc; +} + +static void bnxt_re_put_stats_ctx(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_ctx *hctx; + struct bnxt_qplib_res *res; + u16 tid = 0xffff; + + res = &rdev->qplib_res; + hctx = res->hctx; + + if (test_and_clear_bit(BNXT_RE_FLAG_STATS_CTX_ALLOC, &rdev->flags)) { + bnxt_re_net_stats_ctx_free(rdev, hctx->stats.fw_id, tid); + bnxt_qplib_free_stat_mem(res, &hctx->stats); + } +} + +static void bnxt_re_put_stats2_ctx(struct bnxt_re_dev *rdev) +{ + test_and_clear_bit(BNXT_RE_FLAG_STATS_CTX2_ALLOC, &rdev->flags); +} + +static int bnxt_re_get_stats_ctx(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_ctx *hctx; + struct bnxt_qplib_res *res; + u16 tid = 0xffff; + int rc; + + res = &rdev->qplib_res; + hctx = res->hctx; + + rc = bnxt_qplib_alloc_stat_mem(res->pdev, rdev->chip_ctx, &hctx->stats); + if (rc) + return -ENOMEM; + rc = bnxt_re_net_stats_ctx_alloc(rdev, tid); + if (rc) + goto free_stat_mem; + set_bit(BNXT_RE_FLAG_STATS_CTX_ALLOC, &rdev->flags); + + return 0; + +free_stat_mem: + bnxt_qplib_free_stat_mem(res, &hctx->stats); + + return rc; +} + +static int bnxt_re_update_dev_attr(struct bnxt_re_dev *rdev) +{ + int rc; + + rc = bnxt_qplib_get_dev_attr(&rdev->rcfw); + if (rc) + return rc; + if (!bnxt_re_check_min_attr(rdev)) + return -EINVAL; + return 0; +} + +static void bnxt_re_free_tbls(struct bnxt_re_dev *rdev) +{ + bnxt_qplib_clear_tbls(&rdev->qplib_res); + bnxt_qplib_free_tbls(&rdev->qplib_res); +} + +static int bnxt_re_alloc_init_tbls(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_chip_ctx *chip_ctx = rdev->chip_ctx; + u8 pppp_factor = 0; + int rc; + + /* + * TODO: Need a better mechanism for spreading of the + * 512 extended PPP pages. For now, spreading it + * based on port_count + */ + if (_is_chip_p7(chip_ctx) && chip_ctx->modes.db_push) + pppp_factor = rdev->en_dev->port_count; + rc = bnxt_qplib_alloc_tbls(&rdev->qplib_res, pppp_factor); + if (rc) + return rc; + bnxt_qplib_init_tbls(&rdev->qplib_res); + set_bit(BNXT_RE_FLAG_TBLS_ALLOCINIT, &rdev->flags); + + return 0; +} + +static void bnxt_re_clean_nqs(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_nq *nq; + int i; + + if (!rdev->nqr.max_init) + return; + + for (i = (rdev->nqr.max_init - 1) ; i >= 0; i--) { + nq = &rdev->nqr.nq[i]; + bnxt_qplib_disable_nq(nq); + bnxt_re_net_ring_free(rdev, nq->ring_id); + bnxt_qplib_free_nq_mem(nq); + } + rdev->nqr.max_init = 0; +} + +static int bnxt_re_setup_nqs(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_ring_attr rattr = {}; + struct bnxt_qplib_nq *nq; + int rc, i; + int depth; + u32 offt; + u16 vec; + + mutex_init(&rdev->nqr.load_lock); + /* + * TODO: Optimize the depth based on the + * number of NQs. + */ + depth = BNXT_QPLIB_NQE_MAX_CNT; + for (i = 0; i < rdev->nqr.num_msix - 1; i++) { + nq = &rdev->nqr.nq[i]; + vec = rdev->nqr.msix_entries[i + 1].vector; + offt = rdev->nqr.msix_entries[i + 1].db_offset; + nq->hwq.max_elements = depth; + rc = bnxt_qplib_alloc_nq_mem(&rdev->qplib_res, nq); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to get mem for NQ %d, rc = 0x%x", + i, rc); + goto fail_mem; + } + + rattr.dma_arr = nq->hwq.pbl[PBL_LVL_0].pg_map_arr; + rattr.pages = nq->hwq.pbl[rdev->nqr.nq[i].hwq.level].pg_count; + rattr.type = bnxt_re_get_rtype(rdev); + rattr.mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; + rattr.depth = nq->hwq.max_elements - 1; + rattr.lrid = rdev->nqr.msix_entries[i + 1].ring_idx; + + /* Set DBR pacing capability on the first NQ ring only */ + if (!i && bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) + rattr.flags = HWRM_RING_ALLOC_INPUT_FLAGS_NQ_DBR_PACING; + else + rattr.flags = 0; + + rc = bnxt_re_net_ring_alloc(rdev, &rattr, &nq->ring_id); + if (rc) { + nq->ring_id = 0xffff; /* Invalid ring-id */ + dev_err(rdev_to_dev(rdev), + "Failed to get fw id for NQ %d, rc = 0x%x", + i, rc); + goto fail_ring; + } + + rc = bnxt_qplib_enable_nq(nq, i, vec, offt, + &bnxt_re_cqn_handler, + &bnxt_re_srqn_handler); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to enable NQ %d, rc = 0x%x", i, rc); + goto fail_en; + } + } + + rdev->nqr.max_init = i; + return 0; +fail_en: + /* *nq was i'th nq */ + bnxt_re_net_ring_free(rdev, nq->ring_id); +fail_ring: + bnxt_qplib_free_nq_mem(nq); +fail_mem: + rdev->nqr.max_init = i; + return rc; +} + +static void bnxt_re_sysfs_destroy_file(struct bnxt_re_dev *rdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bnxt_re_attributes); i++) + device_remove_file(&rdev->ibdev.dev, bnxt_re_attributes[i]); +} + +static int bnxt_re_sysfs_create_file(struct bnxt_re_dev *rdev) +{ + int i, j, rc = 0; + + for (i = 0; i < ARRAY_SIZE(bnxt_re_attributes); i++) { + rc = device_create_file(&rdev->ibdev.dev, + bnxt_re_attributes[i]); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to create IB sysfs with rc = 0x%x", rc); + /* Must clean up all created device files */ + for (j = 0; j < i; j++) + device_remove_file(&rdev->ibdev.dev, + bnxt_re_attributes[j]); + clear_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags); + ib_unregister_device(&rdev->ibdev); + return 1; + } + } + return 0; +} + +/* worker thread for polling periodic events. Now used for QoS programming*/ +static void bnxt_re_worker(struct work_struct *work) +{ + struct bnxt_re_dev *rdev = container_of(work, struct bnxt_re_dev, + worker.work); + int rc; + + /* QoS is in 30s cadence for PFs*/ + if (!rdev->is_virtfn && !rdev->worker_30s--) + rdev->worker_30s = 30; + /* Use trylock for bnxt_re_dev_lock as this can be + * held for long time by debugfs show path while issuing + * HWRMS. If the debugfs name update is not done in this + * iteration, the driver will check for the same in the + * next schedule of the worker i.e after 1 sec. + */ + if (mutex_trylock(&bnxt_re_dev_lock)) + mutex_unlock(&bnxt_re_dev_lock); + + if (!rdev->stats.stats_query_sec) + goto resched; + + if (test_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, &rdev->flags) && + (rdev->is_virtfn || + !_is_ext_stats_supported(rdev->dev_attr->dev_cap_flags))) { + if (!(rdev->stats.stats_query_counter++ % + rdev->stats.stats_query_sec)) { + rc = bnxt_re_get_qos_stats(rdev); + if (rc && rc != -ENOMEM) + clear_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, + &rdev->flags); + } + } + +resched: + schedule_delayed_work(&rdev->worker, msecs_to_jiffies(1000)); +} + +static int bnxt_re_alloc_dbr_sw_stats_mem(struct bnxt_re_dev *rdev) +{ + if (!(rdev->dbr_drop_recov || rdev->dbr_pacing)) + return 0; + + rdev->dbr_sw_stats = kzalloc(sizeof(*rdev->dbr_sw_stats), GFP_KERNEL); + if (!rdev->dbr_sw_stats) + return -ENOMEM; + + return 0; +} + +static void bnxt_re_free_dbr_sw_stats_mem(struct bnxt_re_dev *rdev) +{ + kfree(rdev->dbr_sw_stats); + rdev->dbr_sw_stats = NULL; +} + +static int bnxt_re_initialize_dbr_drop_recov(struct bnxt_re_dev *rdev) +{ + rdev->dbr_drop_recov_wq = + create_singlethread_workqueue("bnxt_re_dbr_drop_recov"); + if (!rdev->dbr_drop_recov_wq) { + dev_err(rdev_to_dev(rdev), "DBR Drop Revov wq alloc failed!"); + return -EINVAL; + } + rdev->dbr_drop_recov = true; + + /* Enable configfs setting dbr_drop_recov by default*/ + rdev->user_dbr_drop_recov = true; + + rdev->user_dbr_drop_recov_timeout = BNXT_RE_DBR_RECOV_USERLAND_TIMEOUT; + return 0; +} + +static void bnxt_re_deinitialize_dbr_drop_recov(struct bnxt_re_dev *rdev) +{ + if (rdev->dbr_drop_recov_wq) { + flush_workqueue(rdev->dbr_drop_recov_wq); + destroy_workqueue(rdev->dbr_drop_recov_wq); + rdev->dbr_drop_recov_wq = NULL; + } + rdev->dbr_drop_recov = false; +} + +static int bnxt_re_initialize_dbr_pacing(struct bnxt_re_dev *rdev) +{ + int rc; + + /* Allocate a page for app use */ + rdev->dbr_page = (void *)__get_free_page(GFP_KERNEL); + if (!rdev->dbr_page) { + dev_err(rdev_to_dev(rdev), "DBR page allocation failed!"); + return -ENOMEM; + } + memset((u8 *)rdev->dbr_page, 0, PAGE_SIZE); + rdev->qplib_res.pacing_data = (struct bnxt_qplib_db_pacing_data *)rdev->dbr_page; + rc = bnxt_re_hwrm_dbr_pacing_qcfg(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query dbr pacing config %d\n", rc); + goto fail; + } + /* Create a work queue for scheduling dbq event */ + rdev->dbq_wq = create_singlethread_workqueue("bnxt_re_dbq"); + if (!rdev->dbq_wq) { + dev_err(rdev_to_dev(rdev), "DBQ wq alloc failed!"); + rc = -ENOMEM; + goto fail; + } + /* MAP grc window 2 for reading db fifo depth */ + writel_fbsd(rdev->en_dev->softc, BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4, 0, + rdev->chip_ctx->dbr_stat_db_fifo & BNXT_GRC_BASE_MASK); + rdev->dbr_db_fifo_reg_off = + (rdev->chip_ctx->dbr_stat_db_fifo & BNXT_GRC_OFFSET_MASK) + + 0x2000; + rdev->qplib_res.pacing_data->grc_reg_offset = rdev->dbr_db_fifo_reg_off; + + rdev->dbr_bar_addr = + pci_resource_start(rdev->qplib_res.pdev, 0) + + rdev->dbr_db_fifo_reg_off; + + /* Percentage of DB FIFO */ + rdev->dbq_watermark = BNXT_RE_PACING_DBQ_THRESHOLD; + rdev->pacing_en_int_th = BNXT_RE_PACING_EN_INT_THRESHOLD; + rdev->pacing_algo_th = BNXT_RE_PACING_ALGO_THRESHOLD; + rdev->dbq_pacing_time = BNXT_RE_DBR_INT_TIME; + rdev->dbr_def_do_pacing = BNXT_RE_DBR_DO_PACING_NO_CONGESTION; + rdev->do_pacing_save = rdev->dbr_def_do_pacing; + bnxt_re_set_default_pacing_data(rdev); + dev_dbg(rdev_to_dev(rdev), "Initialized db pacing\n"); + + return 0; +fail: + free_page((u64)rdev->dbr_page); + rdev->dbr_page = NULL; + return rc; +} + +static void bnxt_re_deinitialize_dbr_pacing(struct bnxt_re_dev *rdev) +{ + if (rdev->dbq_wq) + flush_workqueue(rdev->dbq_wq); + + cancel_work_sync(&rdev->dbq_fifo_check_work); + cancel_delayed_work_sync(&rdev->dbq_pacing_work); + + if (rdev->dbq_wq) { + destroy_workqueue(rdev->dbq_wq); + rdev->dbq_wq = NULL; + } + + if (rdev->dbr_page) + free_page((u64)rdev->dbr_page); + rdev->dbr_page = NULL; + rdev->dbr_pacing = false; +} + +/* enable_dbr_pacing needs to be done only for older FWs + * where host selects primary function. ie. pacing_ext + * flags is not set. + */ +int bnxt_re_enable_dbr_pacing(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_nq *nq; + + nq = &rdev->nqr.nq[0]; + rdev->dbq_nq_id = nq->ring_id; + + if (!bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx) && + bnxt_qplib_dbr_pacing_is_primary_pf(rdev->chip_ctx)) { + if (bnxt_re_hwrm_dbr_pacing_cfg(rdev, true)) { + dev_err(rdev_to_dev(rdev), + "Failed to set dbr pacing config\n"); + return -EIO; + } + /* MAP grc window 8 for ARMing the NQ DBQ */ + writel_fbsd(rdev->en_dev->softc, BNXT_GRCPF_REG_WINDOW_BASE_OUT + 28 , 0, + rdev->chip_ctx->dbr_aeq_arm_reg & BNXT_GRC_BASE_MASK); + rdev->dbr_aeq_arm_reg_off = + (rdev->chip_ctx->dbr_aeq_arm_reg & + BNXT_GRC_OFFSET_MASK) + 0x8000; + writel_fbsd(rdev->en_dev->softc, rdev->dbr_aeq_arm_reg_off , 0, 1); + } + + return 0; +} + +/* disable_dbr_pacing needs to be done only for older FWs + * where host selects primary function. ie. pacing_ext + * flags is not set. + */ + +int bnxt_re_disable_dbr_pacing(struct bnxt_re_dev *rdev) +{ + int rc = 0; + + if (!bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx) && + bnxt_qplib_dbr_pacing_is_primary_pf(rdev->chip_ctx)) + rc = bnxt_re_hwrm_dbr_pacing_cfg(rdev, false); + + return rc; +} + +static void bnxt_re_ib_uninit(struct bnxt_re_dev *rdev) +{ + if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) { + bnxt_re_sysfs_destroy_file(rdev); + /* Cleanup ib dev */ + ib_unregister_device(&rdev->ibdev); + clear_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags); + return; + } +} + +static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) +{ + struct bnxt_qplib_dpi *kdpi; + int rc, wait_count = BNXT_RE_RES_FREE_WAIT_COUNT; + + bnxt_re_net_unregister_async_event(rdev); + + bnxt_re_put_stats2_ctx(rdev); + if (test_and_clear_bit(BNXT_RE_FLAG_DEV_LIST_INITIALIZED, + &rdev->flags)) { + /* did the caller hold the lock? */ + mutex_lock(&bnxt_re_dev_lock); + list_del_rcu(&rdev->list); + mutex_unlock(&bnxt_re_dev_lock); + } + + bnxt_re_uninit_resolve_wq(rdev); + bnxt_re_uninit_dcb_wq(rdev); + bnxt_re_uninit_aer_wq(rdev); + + bnxt_re_deinitialize_dbr_drop_recov(rdev); + + if (bnxt_qplib_dbr_pacing_en(rdev->chip_ctx)) + (void)bnxt_re_disable_dbr_pacing(rdev); + + if (test_and_clear_bit(BNXT_RE_FLAG_WORKER_REG, &rdev->flags)) { + cancel_delayed_work_sync(&rdev->worker); + } + + /* Wait for ULPs to release references */ + while (atomic_read(&rdev->stats.rsors.cq_count) && --wait_count) + usleep_range(500, 1000); + if (!wait_count) + dev_err(rdev_to_dev(rdev), + "CQ resources not freed by stack, count = 0x%x", + atomic_read(&rdev->stats.rsors.cq_count)); + + kdpi = &rdev->dpi_privileged; + if (kdpi->umdbr) { /* kernel DPI was allocated with success */ + (void)bnxt_qplib_dealloc_dpi(&rdev->qplib_res, kdpi); + /* + * Driver just need to know no command had failed + * during driver load sequence and below command is + * required indeed. Piggybacking dpi allocation status. + */ + } + + /* Protect the device uninitialization and start_irq/stop_irq L2 + * callbacks with rtnl lock to avoid race condition between these calls + */ + rtnl_lock(); + if (test_and_clear_bit(BNXT_RE_FLAG_SETUP_NQ, &rdev->flags)) + bnxt_re_clean_nqs(rdev); + rtnl_unlock(); + + if (test_and_clear_bit(BNXT_RE_FLAG_TBLS_ALLOCINIT, &rdev->flags)) + bnxt_re_free_tbls(rdev); + if (test_and_clear_bit(BNXT_RE_FLAG_RCFW_CHANNEL_INIT, &rdev->flags)) { + rc = bnxt_qplib_deinit_rcfw(&rdev->rcfw); + if (rc) + dev_warn(rdev_to_dev(rdev), + "Failed to deinitialize fw, rc = 0x%x", rc); + } + + bnxt_re_put_stats_ctx(rdev); + + if (test_and_clear_bit(BNXT_RE_FLAG_ALLOC_CTX, &rdev->flags)) + bnxt_qplib_free_hwctx(&rdev->qplib_res); + + rtnl_lock(); + if (test_and_clear_bit(BNXT_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags)) + bnxt_qplib_disable_rcfw_channel(&rdev->rcfw); + + if (rdev->dbr_pacing) + bnxt_re_deinitialize_dbr_pacing(rdev); + + bnxt_re_free_dbr_sw_stats_mem(rdev); + + if (test_and_clear_bit(BNXT_RE_FLAG_NET_RING_ALLOC, &rdev->flags)) + bnxt_re_net_ring_free(rdev, rdev->rcfw.creq.ring_id); + + if (test_and_clear_bit(BNXT_RE_FLAG_ALLOC_RCFW, &rdev->flags)) + bnxt_qplib_free_rcfw_channel(&rdev->qplib_res); + + if (test_and_clear_bit(BNXT_RE_FLAG_GOT_MSIX, &rdev->flags)) + bnxt_re_free_msix(rdev); + rtnl_unlock(); + + bnxt_re_destroy_chip_ctx(rdev); + + if (op_type != BNXT_RE_PRE_RECOVERY_REMOVE) { + if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, + &rdev->flags)) + bnxt_re_unregister_netdev(rdev); + } +} + +static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type, u8 wqe_mode) +{ + struct bnxt_re_ring_attr rattr = {}; + struct bnxt_qplib_creq_ctx *creq; + int vec, offset; + int rc = 0; + + if (op_type != BNXT_RE_POST_RECOVERY_INIT) { + /* Registered a new RoCE device instance to netdev */ + rc = bnxt_re_register_netdev(rdev); + if (rc) + return -EINVAL; + } + set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); + + rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); + if (rc) { + dev_err(rdev_to_dev(rdev), "Failed to get chip context rc 0x%x", rc); + bnxt_re_unregister_netdev(rdev); + clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); + rc = -EINVAL; + return rc; + } + + /* Protect the device initialization and start_irq/stop_irq L2 callbacks + * with rtnl lock to avoid race condition between these calls + */ + rtnl_lock(); + rc = bnxt_re_request_msix(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Requesting MSI-X vectors failed with rc = 0x%x", rc); + rc = -EINVAL; + goto release_rtnl; + } + set_bit(BNXT_RE_FLAG_GOT_MSIX, &rdev->flags); + + /* Establish RCFW Communication Channel to initialize the context + memory for the function and all child VFs */ + rc = bnxt_qplib_alloc_rcfw_channel(&rdev->qplib_res); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to alloc mem for rcfw, rc = %#x\n", rc); + goto release_rtnl; + } + set_bit(BNXT_RE_FLAG_ALLOC_RCFW, &rdev->flags); + + creq = &rdev->rcfw.creq; + rattr.dma_arr = creq->hwq.pbl[PBL_LVL_0].pg_map_arr; + rattr.pages = creq->hwq.pbl[creq->hwq.level].pg_count; + rattr.type = bnxt_re_get_rtype(rdev); + rattr.mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; + rattr.depth = BNXT_QPLIB_CREQE_MAX_CNT - 1; + rattr.lrid = rdev->nqr.msix_entries[BNXT_RE_AEQ_IDX].ring_idx; + rc = bnxt_re_net_ring_alloc(rdev, &rattr, &creq->ring_id); + if (rc) { + creq->ring_id = 0xffff; + dev_err(rdev_to_dev(rdev), + "Failed to allocate CREQ fw id with rc = 0x%x", rc); + goto release_rtnl; + } + + if (!rdev->chip_ctx) + goto release_rtnl; + /* Program the NQ ID for DBQ notification */ + if (rdev->chip_ctx->modes.dbr_pacing_v0 || + bnxt_qplib_dbr_pacing_en(rdev->chip_ctx) || + bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { + rc = bnxt_re_initialize_dbr_pacing(rdev); + if (!rc) + rdev->dbr_pacing = true; + else + rdev->dbr_pacing = false; + dev_dbg(rdev_to_dev(rdev), "%s: initialize db pacing ret %d\n", + __func__, rc); + } + + vec = rdev->nqr.msix_entries[BNXT_RE_AEQ_IDX].vector; + offset = rdev->nqr.msix_entries[BNXT_RE_AEQ_IDX].db_offset; + rc = bnxt_qplib_enable_rcfw_channel(&rdev->rcfw, vec, offset, + &bnxt_re_aeq_handler); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to enable RCFW channel with rc = 0x%x", rc); + goto release_rtnl; + } + set_bit(BNXT_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags); + + rc = bnxt_re_update_dev_attr(rdev); + if (rc) + goto release_rtnl; + bnxt_re_set_resource_limits(rdev); + if (!rdev->is_virtfn && !_is_chip_gen_p5_p7(rdev->chip_ctx)) { + rc = bnxt_qplib_alloc_hwctx(&rdev->qplib_res); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to alloc hw contexts, rc = 0x%x", rc); + goto release_rtnl; + } + set_bit(BNXT_RE_FLAG_ALLOC_CTX, &rdev->flags); + } + + rc = bnxt_re_get_stats_ctx(rdev); + if (rc) + goto release_rtnl; + + rc = bnxt_qplib_init_rcfw(&rdev->rcfw, rdev->is_virtfn); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to initialize fw with rc = 0x%x", rc); + goto release_rtnl; + } + set_bit(BNXT_RE_FLAG_RCFW_CHANNEL_INIT, &rdev->flags); + + /* Based resource count on the 'new' device caps */ + rc = bnxt_re_update_dev_attr(rdev); + if (rc) + goto release_rtnl; + rc = bnxt_re_alloc_init_tbls(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), "tbls alloc-init failed rc = %#x", + rc); + goto release_rtnl; + } + rc = bnxt_re_setup_nqs(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), "NQs alloc-init failed rc = %#x\n", + rc); + if (rdev->nqr.max_init == 0) + goto release_rtnl; + + dev_warn(rdev_to_dev(rdev), + "expected nqs %d available nqs %d\n", + rdev->nqr.num_msix, rdev->nqr.max_init); + } + set_bit(BNXT_RE_FLAG_SETUP_NQ, &rdev->flags); + rtnl_unlock(); + + rc = bnxt_qplib_alloc_dpi(&rdev->qplib_res, &rdev->dpi_privileged, + rdev, BNXT_QPLIB_DPI_TYPE_KERNEL); + if (rc) + goto fail; + + if (rdev->dbr_pacing) + bnxt_re_enable_dbr_pacing(rdev); + + if (rdev->chip_ctx->modes.dbr_drop_recov) + bnxt_re_initialize_dbr_drop_recov(rdev); + + rc = bnxt_re_alloc_dbr_sw_stats_mem(rdev); + if (rc) + goto fail; + + /* This block of code is needed for error recovery support */ + if (!rdev->is_virtfn) { + struct bnxt_re_tc_rec *tc_rec; + + tc_rec = &rdev->tc_rec[0]; + rc = bnxt_re_query_hwrm_qportcfg(rdev, tc_rec, 0xFFFF); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to query port config rc:%d", rc); + return rc; + } + + /* Query f/w defaults of CC params */ + rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &rdev->cc_param); + if (rc) + dev_warn(rdev_to_dev(rdev), + "Failed to query CC defaults\n"); + if (1) { + rdev->num_vfs = pci_num_vf(rdev->en_dev->pdev); + if (rdev->num_vfs) { + bnxt_re_set_resource_limits(rdev); + bnxt_qplib_set_func_resources(&rdev->qplib_res); + } + } + } + INIT_DELAYED_WORK(&rdev->worker, bnxt_re_worker); + set_bit(BNXT_RE_FLAG_WORKER_REG, &rdev->flags); + schedule_delayed_work(&rdev->worker, msecs_to_jiffies(1000)); + + bnxt_re_init_dcb_wq(rdev); + bnxt_re_init_aer_wq(rdev); + bnxt_re_init_resolve_wq(rdev); + mutex_lock(&bnxt_re_dev_lock); + list_add_tail_rcu(&rdev->list, &bnxt_re_dev_list); + /* Added to the list, not in progress anymore */ + gadd_dev_inprogress--; + set_bit(BNXT_RE_FLAG_DEV_LIST_INITIALIZED, &rdev->flags); + mutex_unlock(&bnxt_re_dev_lock); + + + return rc; +release_rtnl: + rtnl_unlock(); +fail: + bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE); + + return rc; +} + +static int bnxt_re_ib_init(struct bnxt_re_dev *rdev) +{ + int rc = 0; + + rc = bnxt_re_register_ib(rdev); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Register IB failed with rc = 0x%x", rc); + goto fail; + } + if (bnxt_re_sysfs_create_file(rdev)) { + bnxt_re_stopqps_and_ib_uninit(rdev); + goto fail; + } + + set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags); + set_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags); + set_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, &rdev->flags); + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_PORT_ACTIVE); + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_GID_CHANGE); + + return rc; +fail: + bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE); + return rc; +} + +/* wrapper for ib_init funcs */ +int _bnxt_re_ib_init(struct bnxt_re_dev *rdev) +{ + return bnxt_re_ib_init(rdev); +} + +/* wrapper for aux init funcs */ +int _bnxt_re_ib_init2(struct bnxt_re_dev *rdev) +{ + bnxt_re_ib_init_2(rdev); + return 0; /* add return for future proof */ +} + +static void bnxt_re_dev_unreg(struct bnxt_re_dev *rdev) +{ + bnxt_re_dev_dealloc(rdev); +} + + +static int bnxt_re_dev_reg(struct bnxt_re_dev **rdev, struct ifnet *netdev, + struct bnxt_en_dev *en_dev) +{ + struct ifnet *realdev = NULL; + + realdev = netdev; + if (realdev) + dev_dbg(NULL, "%s: realdev = %p netdev = %p\n", __func__, + realdev, netdev); + /* + * Note: + * The first argument to bnxt_re_dev_alloc() is 'netdev' and + * not 'realdev', since in the case of bonding we want to + * register the bonded virtual netdev (master) to the ib stack. + * And 'en_dev' (for L2/PCI communication) is the first slave + * device (PF0 on the card). + * In the case of a regular netdev, both netdev and the en_dev + * correspond to the same device. + */ + *rdev = bnxt_re_dev_alloc(netdev, en_dev); + if (!*rdev) { + pr_err("%s: netdev %p not handled", + ROCE_DRV_MODULE_NAME, netdev); + return -ENOMEM; + } + bnxt_re_hold(*rdev); + + return 0; +} + +void bnxt_re_get_link_speed(struct bnxt_re_dev *rdev) +{ + rdev->espeed = rdev->en_dev->espeed; + return; +} + +void bnxt_re_stopqps_and_ib_uninit(struct bnxt_re_dev *rdev) +{ + dev_dbg(rdev_to_dev(rdev), "%s: Stopping QPs, IB uninit on rdev: %p\n", + __func__, rdev); + bnxt_re_stop_all_nonqp1_nonshadow_qps(rdev); + bnxt_re_ib_uninit(rdev); +} + +void bnxt_re_remove_device(struct bnxt_re_dev *rdev, u8 op_type, + struct auxiliary_device *aux_dev) +{ + struct bnxt_re_en_dev_info *en_info; + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_rcfw *rcfw; + + rcfw = &rdev->rcfw; + cmdq = &rcfw->cmdq; + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); + + dev_dbg(rdev_to_dev(rdev), "%s: Removing rdev: %p\n", __func__, rdev); + bnxt_re_dev_uninit(rdev, op_type); + en_info = auxiliary_get_drvdata(aux_dev); + if (en_info) { + rtnl_lock(); + en_info->rdev = NULL; + rtnl_unlock(); + if (op_type != BNXT_RE_PRE_RECOVERY_REMOVE) { + clear_bit(BNXT_RE_FLAG_EN_DEV_PRIMARY_DEV, &en_info->flags); + clear_bit(BNXT_RE_FLAG_EN_DEV_SECONDARY_DEV, &en_info->flags); + clear_bit(BNXT_RE_FLAG_EN_DEV_NETDEV_REG, &en_info->flags); + } + } + bnxt_re_dev_unreg(rdev); +} + +int bnxt_re_add_device(struct bnxt_re_dev **rdev, + struct ifnet *netdev, + u8 qp_mode, u8 op_type, u8 wqe_mode, + u32 num_msix_requested, + struct auxiliary_device *aux_dev) +{ + struct bnxt_re_en_dev_info *en_info; + struct bnxt_en_dev *en_dev; + int rc = 0; + + en_info = auxiliary_get_drvdata(aux_dev); + en_dev = en_info->en_dev; + + mutex_lock(&bnxt_re_dev_lock); + /* Check if driver already in mod exit and aux_dev is valid */ + if (gmod_exit || !aux_dev) { + mutex_unlock(&bnxt_re_dev_lock); + return -ENODEV; + } + /* Add device in progress */ + gadd_dev_inprogress++; + mutex_unlock(&bnxt_re_dev_lock); + + rc = bnxt_re_dev_reg(rdev, netdev, en_dev); + if (rc) { + dev_dbg(NULL, "Failed to create add device for netdev %p\n", + netdev); + /* + * For BNXT_RE_POST_RECOVERY_INIT special case + * called from bnxt_re_start, the work is + * complete only after, bnxt_re_start completes + * bnxt_unregister_device in case of failure. + * So bnxt_re_start will decrement gadd_dev_inprogress + * in case of failure. + */ + if (op_type != BNXT_RE_POST_RECOVERY_INIT) { + mutex_lock(&bnxt_re_dev_lock); + gadd_dev_inprogress--; + mutex_unlock(&bnxt_re_dev_lock); + } + return rc; + } + + if (rc != 0) + goto ref_error; + + /* + * num_msix_requested = BNXT_RE_MSIX_FROM_MOD_PARAM indicates fresh driver load. + * Otherwaise, this invocation can be the result of lag create / destroy, + * err revovery, hot fw upgrade, etc.. + */ + if (num_msix_requested == BNXT_RE_MSIX_FROM_MOD_PARAM) { + if (bnxt_re_probe_count < BNXT_RE_MAX_DEVICES) + num_msix_requested = max_msix_vec[bnxt_re_probe_count++]; + else + /* Consider as default when probe_count exceeds its limit */ + num_msix_requested = 0; + + /* if user specifies only one value, use the same for all PFs */ + if (max_msix_vec_argc == 1) + num_msix_requested = max_msix_vec[0]; + } + + (*rdev)->num_msix_requested = num_msix_requested; + (*rdev)->gsi_ctx.gsi_qp_mode = qp_mode; + (*rdev)->adev = aux_dev; + (*rdev)->dev_addr = en_dev->softc->func.mac_addr; + /* Before updating the rdev pointer in bnxt_re_en_dev_info structure, + * take the rtnl lock to avoid accessing invalid rdev pointer from + * L2 ULP callbacks. This is applicable in all the places where rdev + * pointer is updated in bnxt_re_en_dev_info. + */ + rtnl_lock(); + en_info->rdev = *rdev; + rtnl_unlock(); + rc = bnxt_re_dev_init(*rdev, op_type, wqe_mode); + if (rc) { +ref_error: + bnxt_re_dev_unreg(*rdev); + *rdev = NULL; + /* + * For BNXT_RE_POST_RECOVERY_INIT special case + * called from bnxt_re_start, the work is + * complete only after, bnxt_re_start completes + * bnxt_unregister_device in case of failure. + * So bnxt_re_start will decrement gadd_dev_inprogress + * in case of failure. + */ + if (op_type != BNXT_RE_POST_RECOVERY_INIT) { + mutex_lock(&bnxt_re_dev_lock); + gadd_dev_inprogress--; + mutex_unlock(&bnxt_re_dev_lock); + } + } + dev_dbg(rdev_to_dev(*rdev), "%s: Adding rdev: %p\n", __func__, *rdev); + if (!rc) { + set_bit(BNXT_RE_FLAG_EN_DEV_NETDEV_REG, &en_info->flags); + } + return rc; +} + +struct bnxt_re_dev *bnxt_re_get_peer_pf(struct bnxt_re_dev *rdev) +{ + struct pci_dev *pdev_in = rdev->en_dev->pdev; + int tmp_bus_num, bus_num = pdev_in->bus->number; + int tmp_dev_num, dev_num = PCI_SLOT(pdev_in->devfn); + int tmp_func_num, func_num = PCI_FUNC(pdev_in->devfn); + struct bnxt_re_dev *tmp_rdev; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_rdev, &bnxt_re_dev_list, list) { + tmp_bus_num = tmp_rdev->en_dev->pdev->bus->number; + tmp_dev_num = PCI_SLOT(tmp_rdev->en_dev->pdev->devfn); + tmp_func_num = PCI_FUNC(tmp_rdev->en_dev->pdev->devfn); + + if (bus_num == tmp_bus_num && dev_num == tmp_dev_num && + func_num != tmp_func_num) { + rcu_read_unlock(); + return tmp_rdev; + } + } + rcu_read_unlock(); + return NULL; +} + + +int bnxt_re_schedule_work(struct bnxt_re_dev *rdev, unsigned long event, + struct ifnet *vlan_dev, + struct ifnet *netdev, + struct auxiliary_device *adev) +{ + struct bnxt_re_work *re_work; + + /* Allocate for the deferred task */ + re_work = kzalloc(sizeof(*re_work), GFP_KERNEL); + if (!re_work) + return -ENOMEM; + + re_work->rdev = rdev; + re_work->event = event; + re_work->vlan_dev = vlan_dev; + re_work->adev = adev; + INIT_WORK(&re_work->work, bnxt_re_task); + if (rdev) + atomic_inc(&rdev->sched_count); + re_work->netdev = netdev; + queue_work(bnxt_re_wq, &re_work->work); + + return 0; +} + + +int bnxt_re_get_slot_pf_count(struct bnxt_re_dev *rdev) +{ + struct pci_dev *pdev_in = rdev->en_dev->pdev; + int tmp_bus_num, bus_num = pdev_in->bus->number; + int tmp_dev_num, dev_num = PCI_SLOT(pdev_in->devfn); + struct bnxt_re_dev *tmp_rdev; + int pf_cnt = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_rdev, &bnxt_re_dev_list, list) { + tmp_bus_num = tmp_rdev->en_dev->pdev->bus->number; + tmp_dev_num = PCI_SLOT(tmp_rdev->en_dev->pdev->devfn); + + if (bus_num == tmp_bus_num && dev_num == tmp_dev_num) + pf_cnt++; + } + rcu_read_unlock(); + return pf_cnt; +} + +/* Handle all deferred netevents tasks */ +static void bnxt_re_task(struct work_struct *work) +{ + struct bnxt_re_en_dev_info *en_info; + struct auxiliary_device *aux_dev; + struct bnxt_re_work *re_work; + struct bnxt_re_dev *rdev; + + re_work = container_of(work, struct bnxt_re_work, work); + + mutex_lock(&bnxt_re_mutex); + rdev = re_work->rdev; + + /* + * If the previous rdev is deleted due to bond creation + * do not handle the event + */ + if (!bnxt_re_is_rdev_valid(rdev)) + goto exit; + + /* Ignore the event, if the device is not registred with IB stack. This + * is to avoid handling any event while the device is added/removed. + */ + if (rdev && !test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) { + dev_dbg(rdev_to_dev(rdev), "%s: Ignoring netdev event 0x%lx", + __func__, re_work->event); + goto done; + } + + /* Extra check to silence coverity. We shouldn't handle any event + * when rdev is NULL. + */ + if (!rdev) + goto exit; + + dev_dbg(rdev_to_dev(rdev), "Scheduled work for event 0x%lx", + re_work->event); + + switch (re_work->event) { + case NETDEV_UP: + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, + IB_EVENT_PORT_ACTIVE); + bnxt_re_net_register_async_event(rdev); + break; + + case NETDEV_DOWN: + bnxt_qplib_dbr_pacing_set_primary_pf(rdev->chip_ctx, 0); + bnxt_re_stop_all_nonqp1_nonshadow_qps(rdev); + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, + IB_EVENT_PORT_ERR); + break; + + case NETDEV_CHANGE: + if (bnxt_re_get_link_state(rdev) == IB_PORT_DOWN) { + bnxt_re_stop_all_nonqp1_nonshadow_qps(rdev); + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, + IB_EVENT_PORT_ERR); + break; + } else if (bnxt_re_get_link_state(rdev) == IB_PORT_ACTIVE) { + bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, + IB_EVENT_PORT_ACTIVE); + } + + /* temporarily disable the check for SR2 */ + if (!bnxt_qplib_query_cc_param(&rdev->qplib_res, + &rdev->cc_param) && + !_is_chip_p7(rdev->chip_ctx)) { + /* + * Disable CC for 10G speed + * for non p5 devices + */ + if (rdev->sl_espeed == SPEED_10000 && + !_is_chip_gen_p5_p7(rdev->chip_ctx)) { + if (rdev->cc_param.enable) + bnxt_re_clear_cc(rdev); + } else { + if (!rdev->cc_param.enable && + rdev->cc_param.admin_enable) + bnxt_re_setup_cc(rdev); + } + } + break; + + case NETDEV_UNREGISTER: + bnxt_re_stopqps_and_ib_uninit(rdev); + aux_dev = rdev->adev; + if (re_work->adev) + goto done; + + bnxt_re_remove_device(rdev, BNXT_RE_COMPLETE_REMOVE, aux_dev); + + break; + + default: + break; + } +done: + if (rdev) { + /* memory barrier to guarantee task completion + * before decrementing sched count + */ + mmiowb(); + atomic_dec(&rdev->sched_count); + } +exit: + if (re_work->adev && re_work->event == NETDEV_UNREGISTER) { + en_info = auxiliary_get_drvdata(re_work->adev); + en_info->ib_uninit_done = true; + wake_up(&en_info->waitq); + } + kfree(re_work); + mutex_unlock(&bnxt_re_mutex); +} + +/* + "Notifier chain callback can be invoked for the same chain from + different CPUs at the same time". + + For cases when the netdev is already present, our call to the + register_netdevice_notifier() will actually get the rtnl_lock() + before sending NETDEV_REGISTER and (if up) NETDEV_UP + events. + + But for cases when the netdev is not already present, the notifier + chain is subjected to be invoked from different CPUs simultaneously. + + This is protected by the netdev_mutex. +*/ +static int bnxt_re_netdev_event(struct notifier_block *notifier, + unsigned long event, void *ptr) +{ + struct ifnet *real_dev, *netdev; + struct bnxt_re_dev *rdev = NULL; + + netdev = netdev_notifier_info_to_ifp(ptr); + real_dev = rdma_vlan_dev_real_dev(netdev); + if (!real_dev) + real_dev = netdev; + /* In case of bonding,this will be bond's rdev */ + rdev = bnxt_re_from_netdev(real_dev); + + if (!rdev) + goto exit; + + dev_info(rdev_to_dev(rdev), "%s: Event = %s (0x%lx), rdev %s (real_dev %s)\n", + __func__, bnxt_re_netevent(event), event, + rdev ? rdev->netdev ? if_getdname(rdev->netdev) : "->netdev = NULL" : "= NULL", + (real_dev == netdev) ? "= netdev" : if_getdname(real_dev)); + + if (!test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) + goto exit; + + bnxt_re_hold(rdev); + + if (real_dev != netdev) { + switch (event) { + case NETDEV_UP: + bnxt_re_schedule_work(rdev, event, netdev, + NULL, NULL); + break; + case NETDEV_DOWN: + break; + default: + break; + } + goto done; + } + + switch (event) { + case NETDEV_CHANGEADDR: + if (!_is_chip_gen_p5_p7(rdev->chip_ctx)) + bnxt_re_update_shadow_ah(rdev); + bnxt_qplib_get_guid(rdev->dev_addr, + (u8 *)&rdev->ibdev.node_guid); + break; + + case NETDEV_CHANGE: + bnxt_re_get_link_speed(rdev); + bnxt_re_schedule_work(rdev, event, NULL, NULL, NULL); + break; + case NETDEV_UNREGISTER: + /* netdev notifier will call NETDEV_UNREGISTER again later since + * we are still holding the reference to the netdev + */ + + /* + * Workaround to avoid ib_unregister hang. Check for module + * reference and dont free up the device if the reference + * is non zero. Checking only for PF functions. + */ + + if (rdev) { + dev_info(rdev_to_dev(rdev), + "bnxt_re:Unreg recvd when module refcnt > 0"); + dev_info(rdev_to_dev(rdev), + "bnxt_re:Close all apps using bnxt_re devs"); + dev_info(rdev_to_dev(rdev), + "bnxt_re:Remove the configfs entry created for the device"); + dev_info(rdev_to_dev(rdev), + "bnxt_re:Refer documentation for details"); + goto done; + } + + if (atomic_read(&rdev->sched_count) > 0) + goto done; + if (!rdev->unreg_sched) { + bnxt_re_schedule_work(rdev, NETDEV_UNREGISTER, + NULL, NULL, NULL); + rdev->unreg_sched = true; + goto done; + } + + break; + default: + break; + } +done: + if (rdev) + bnxt_re_put(rdev); +exit: + return NOTIFY_DONE; +} + +static struct notifier_block bnxt_re_netdev_notifier = { + .notifier_call = bnxt_re_netdev_event +}; + +static void bnxt_re_remove_base_interface(struct bnxt_re_dev *rdev, + struct auxiliary_device *adev) +{ + bnxt_re_stopqps_and_ib_uninit(rdev); + bnxt_re_remove_device(rdev, BNXT_RE_COMPLETE_REMOVE, adev); + auxiliary_set_drvdata(adev, NULL); +} + +/* + * bnxt_re_remove - Removes the roce aux device + * @adev - aux device pointer + * + * This function removes the roce device. This gets + * called in the mod exit path and pci unbind path. + * If the rdev is bond interace, destroys the lag + * in module exit path, and in pci unbind case + * destroys the lag and recreates other base interface. + * If the device is already removed in error recovery + * path, it just unregister with the L2. + */ +static void bnxt_re_remove(struct auxiliary_device *adev) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev); + struct bnxt_en_dev *en_dev; + struct bnxt_re_dev *rdev; + bool primary_dev = false; + bool secondary_dev = false; + + if (!en_info) + return; + + mutex_lock(&bnxt_re_mutex); + en_dev = en_info->en_dev; + + rdev = en_info->rdev; + + if (rdev && bnxt_re_is_rdev_valid(rdev)) { + if (pci_channel_offline(rdev->rcfw.pdev)) + set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); + + if (test_bit(BNXT_RE_FLAG_EN_DEV_PRIMARY_DEV, &en_info->flags)) + primary_dev = true; + if (test_bit(BNXT_RE_FLAG_EN_DEV_SECONDARY_DEV, &en_info->flags)) + secondary_dev = true; + + /* + * en_dev_info of primary device and secondary device have the + * same rdev pointer when LAG is configured. This rdev pointer + * is rdev of bond interface. + */ + if (!primary_dev && !secondary_dev) { + /* removal of non bond interface */ + bnxt_re_remove_base_interface(rdev, adev); + } else { + /* + * removal of bond primary/secondary interface. In this + * case bond device is already removed, so rdev->binfo + * is NULL. + */ + auxiliary_set_drvdata(adev, NULL); + } + } else { + /* device is removed from ulp stop, unregister the net dev */ + if (test_bit(BNXT_RE_FLAG_EN_DEV_NETDEV_REG, &en_info->flags)) { + rtnl_lock(); + en_dev->en_ops->bnxt_unregister_device(en_dev, + BNXT_ROCE_ULP); + rtnl_unlock(); + } + } + mutex_unlock(&bnxt_re_mutex); + return; +} + +/* wrapper for all external user context callers */ +void _bnxt_re_remove(struct auxiliary_device *adev) +{ + bnxt_re_remove(adev); +} + +static void bnxt_re_ib_init_2(struct bnxt_re_dev *rdev) +{ + int rc; + + rc = bnxt_re_get_device_stats(rdev); + if (rc) + dev_err(rdev_to_dev(rdev), + "Failed initial device stat query"); + + bnxt_re_net_register_async_event(rdev); +} + +static int bnxt_re_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct bnxt_aux_dev *aux_dev = + container_of(adev, struct bnxt_aux_dev, aux_dev); + struct bnxt_re_en_dev_info *en_info; + struct bnxt_en_dev *en_dev = NULL; + struct bnxt_re_dev *rdev; + int rc = -ENODEV; + + if (aux_dev) + en_dev = aux_dev->edev; + + if (!en_dev) + return rc; + + if (en_dev->ulp_version != BNXT_ULP_VERSION) { + pr_err("%s: probe error: bnxt_en ulp version magic %x is not compatible!\n", + ROCE_DRV_MODULE_NAME, en_dev->ulp_version); + return -EINVAL; + } + + en_info = kzalloc(sizeof(*en_info), GFP_KERNEL); + if (!en_info) + return -ENOMEM; + memset(en_info, 0, sizeof(struct bnxt_re_en_dev_info)); + en_info->en_dev = en_dev; + auxiliary_set_drvdata(adev, en_info); + + mutex_lock(&bnxt_re_mutex); + rc = bnxt_re_add_device(&rdev, en_dev->net, + BNXT_RE_GSI_MODE_ALL, + BNXT_RE_COMPLETE_INIT, + BNXT_QPLIB_WQE_MODE_STATIC, + BNXT_RE_MSIX_FROM_MOD_PARAM, adev); + if (rc) { + mutex_unlock(&bnxt_re_mutex); + return rc; + } + + rc = bnxt_re_ib_init(rdev); + if (rc) + goto err; + + bnxt_re_ib_init_2(rdev); + + dev_dbg(rdev_to_dev(rdev), "%s: adev: %p\n", __func__, adev); + rdev->adev = adev; + + mutex_unlock(&bnxt_re_mutex); + + return 0; + +err: + mutex_unlock(&bnxt_re_mutex); + bnxt_re_remove(adev); + + return rc; +} + +static const struct auxiliary_device_id bnxt_re_id_table[] = { + { .name = BNXT_ADEV_NAME ".rdma", }, + {}, +}; + +MODULE_DEVICE_TABLE(auxiliary, bnxt_re_id_table); + +static struct auxiliary_driver bnxt_re_driver = { + .name = "rdma", + .probe = bnxt_re_probe, + .remove = bnxt_re_remove, + .id_table = bnxt_re_id_table, +}; + +static int __init bnxt_re_mod_init(void) +{ + int rc = 0; + + pr_info("%s: %s", ROCE_DRV_MODULE_NAME, drv_version); + + bnxt_re_wq = create_singlethread_workqueue("bnxt_re"); + if (!bnxt_re_wq) + return -ENOMEM; + + rc = bnxt_re_register_netdevice_notifier(&bnxt_re_netdev_notifier); + if (rc) { + pr_err("%s: Cannot register to netdevice_notifier", + ROCE_DRV_MODULE_NAME); + goto err_netdev; + } + + INIT_LIST_HEAD(&bnxt_re_dev_list); + + rc = auxiliary_driver_register(&bnxt_re_driver); + if (rc) { + pr_err("%s: Failed to register auxiliary driver\n", + ROCE_DRV_MODULE_NAME); + goto err_auxdrv; + } + + return 0; + +err_auxdrv: + bnxt_re_unregister_netdevice_notifier(&bnxt_re_netdev_notifier); + +err_netdev: + destroy_workqueue(bnxt_re_wq); + + return rc; +} + +static void __exit bnxt_re_mod_exit(void) +{ + gmod_exit = 1; + auxiliary_driver_unregister(&bnxt_re_driver); + + bnxt_re_unregister_netdevice_notifier(&bnxt_re_netdev_notifier); + + if (bnxt_re_wq) + destroy_workqueue(bnxt_re_wq); +} + +module_init(bnxt_re_mod_init); +module_exit(bnxt_re_mod_exit); diff --git a/sys/dev/bnxt/bnxt_re/qplib_fp.c b/sys/dev/bnxt/bnxt_re/qplib_fp.c new file mode 100644 index 000000000000..3f1b02406f7f --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_fp.c @@ -0,0 +1,3544 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Fast Path Operators + */ + +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/if_ether.h> +#include <linux/hardirq.h> +#include <rdma/ib_mad.h> + +#include "hsi_struct_def.h" +#include "qplib_tlv.h" +#include "qplib_res.h" +#include "qplib_rcfw.h" +#include "qplib_sp.h" +#include "qplib_fp.h" +#include "ib_verbs.h" + +static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp); + +static void bnxt_re_legacy_cancel_phantom_processing(struct bnxt_qplib_qp *qp) +{ + qp->sq.condition = false; + qp->sq.legacy_send_phantom = false; + qp->sq.single = false; +} + +static void __bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_cq *scq, *rcq; + + scq = qp->scq; + rcq = qp->rcq; + + if (!qp->sq.flushed) { + dev_dbg(&scq->hwq.pdev->dev, + "QPLIB: FP: Adding to SQ Flush list = %p\n", + qp); + bnxt_re_legacy_cancel_phantom_processing(qp); + list_add_tail(&qp->sq_flush, &scq->sqf_head); + qp->sq.flushed = true; + } + if (!qp->srq) { + if (!qp->rq.flushed) { + dev_dbg(&rcq->hwq.pdev->dev, + "QPLIB: FP: Adding to RQ Flush list = %p\n", + qp); + list_add_tail(&qp->rq_flush, &rcq->rqf_head); + qp->rq.flushed = true; + } + } +} + +static void bnxt_qplib_acquire_cq_flush_locks(struct bnxt_qplib_qp *qp) + __acquires(&qp->scq->flush_lock) __acquires(&qp->rcq->flush_lock) +{ + /* Interrupts are already disabled in calling functions */ + spin_lock(&qp->scq->flush_lock); + if (qp->scq == qp->rcq) + __acquire(&qp->rcq->flush_lock); + else + spin_lock(&qp->rcq->flush_lock); +} + +static void bnxt_qplib_release_cq_flush_locks(struct bnxt_qplib_qp *qp) + __releases(&qp->scq->flush_lock) __releases(&qp->rcq->flush_lock) +{ + if (qp->scq == qp->rcq) + __release(&qp->rcq->flush_lock); + else + spin_unlock(&qp->rcq->flush_lock); + spin_unlock(&qp->scq->flush_lock); +} + +void bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp) +{ + + bnxt_qplib_acquire_cq_flush_locks(qp); + __bnxt_qplib_add_flush_qp(qp); + bnxt_qplib_release_cq_flush_locks(qp); +} + +static void __bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp) +{ + if (qp->sq.flushed) { + qp->sq.flushed = false; + list_del(&qp->sq_flush); + } + if (!qp->srq) { + if (qp->rq.flushed) { + qp->rq.flushed = false; + list_del(&qp->rq_flush); + } + } +} + +void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp) +{ + + bnxt_qplib_acquire_cq_flush_locks(qp); + __clean_cq(qp->scq, (u64)(unsigned long)qp); + qp->sq.hwq.prod = 0; + qp->sq.hwq.cons = 0; + qp->sq.swq_start = 0; + qp->sq.swq_last = 0; + __clean_cq(qp->rcq, (u64)(unsigned long)qp); + qp->rq.hwq.prod = 0; + qp->rq.hwq.cons = 0; + qp->rq.swq_start = 0; + qp->rq.swq_last = 0; + + __bnxt_qplib_del_flush_qp(qp); + bnxt_qplib_release_cq_flush_locks(qp); +} + +static void bnxt_qpn_cqn_sched_task(struct work_struct *work) +{ + struct bnxt_qplib_nq_work *nq_work = + container_of(work, struct bnxt_qplib_nq_work, work); + + struct bnxt_qplib_cq *cq = nq_work->cq; + struct bnxt_qplib_nq *nq = nq_work->nq; + + if (cq && nq) { + spin_lock_bh(&cq->compl_lock); + if (nq->cqn_handler) { + dev_dbg(&nq->res->pdev->dev, + "%s:Trigger cq = %p event nq = %p\n", + __func__, cq, nq); + nq->cqn_handler(nq, cq); + } + spin_unlock_bh(&cq->compl_lock); + } + kfree(nq_work); +} + +static void bnxt_qplib_put_hdr_buf(struct pci_dev *pdev, + struct bnxt_qplib_hdrbuf *buf) +{ + dma_free_coherent(&pdev->dev, buf->len, buf->va, buf->dma_map); + kfree(buf); +} + +static void *bnxt_qplib_get_hdr_buf(struct pci_dev *pdev, u32 step, u32 cnt) +{ + struct bnxt_qplib_hdrbuf *hdrbuf; + u32 len; + + hdrbuf = kmalloc(sizeof(*hdrbuf), GFP_KERNEL); + if (!hdrbuf) + return NULL; + + len = ALIGN((step * cnt), PAGE_SIZE); + hdrbuf->va = dma_alloc_coherent(&pdev->dev, len, + &hdrbuf->dma_map, GFP_KERNEL); + if (!hdrbuf->va) + goto out; + + hdrbuf->len = len; + hdrbuf->step = step; + return hdrbuf; +out: + kfree(hdrbuf); + return NULL; +} + +void bnxt_qplib_free_hdr_buf(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp) +{ + if (qp->rq_hdr_buf) { + bnxt_qplib_put_hdr_buf(res->pdev, qp->rq_hdr_buf); + qp->rq_hdr_buf = NULL; + } + + if (qp->sq_hdr_buf) { + bnxt_qplib_put_hdr_buf(res->pdev, qp->sq_hdr_buf); + qp->sq_hdr_buf = NULL; + } +} + +int bnxt_qplib_alloc_hdr_buf(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp, u32 sstep, u32 rstep) +{ + struct pci_dev *pdev; + int rc = 0; + + pdev = res->pdev; + if (sstep) { + qp->sq_hdr_buf = bnxt_qplib_get_hdr_buf(pdev, sstep, + qp->sq.max_wqe); + if (!qp->sq_hdr_buf) { + dev_err(&pdev->dev, "QPLIB: Failed to get sq_hdr_buf\n"); + return -ENOMEM; + } + } + + if (rstep) { + qp->rq_hdr_buf = bnxt_qplib_get_hdr_buf(pdev, rstep, + qp->rq.max_wqe); + if (!qp->rq_hdr_buf) { + rc = -ENOMEM; + dev_err(&pdev->dev, "QPLIB: Failed to get rq_hdr_buf\n"); + goto fail; + } + } + + return 0; +fail: + bnxt_qplib_free_hdr_buf(res, qp); + return rc; +} + +/* + * clean_nq - Invalidate cqe from given nq. + * @cq - Completion queue + * + * Traverse whole notification queue and invalidate any completion + * associated cq handler provided by caller. + * Note - This function traverse the hardware queue but do not update + * consumer index. Invalidated cqe(marked from this function) will be + * ignored from actual completion of notification queue. + */ +static void clean_nq(struct bnxt_qplib_cq *cq) +{ + struct bnxt_qplib_hwq *nq_hwq = NULL; + struct bnxt_qplib_nq *nq = NULL; + struct nq_base *hw_nqe = NULL; + struct nq_cn *nqcne = NULL; + u32 peek_flags, peek_cons; + u64 q_handle; + u32 type; + int i; + + nq = cq->nq; + nq_hwq = &nq->hwq; + + spin_lock_bh(&nq_hwq->lock); + peek_flags = nq->nq_db.dbinfo.flags; + peek_cons = nq_hwq->cons; + for (i = 0; i < nq_hwq->max_elements; i++) { + hw_nqe = bnxt_qplib_get_qe(nq_hwq, peek_cons, NULL); + if (!NQE_CMP_VALID(hw_nqe, peek_flags)) + break; + + /* The valid test of the entry must be done first + * before reading any further. + */ + dma_rmb(); + type = le16_to_cpu(hw_nqe->info10_type) & + NQ_BASE_TYPE_MASK; + + /* Processing only NQ_BASE_TYPE_CQ_NOTIFICATION */ + if (type == NQ_BASE_TYPE_CQ_NOTIFICATION) { + nqcne = (struct nq_cn *)hw_nqe; + + q_handle = le32_to_cpu(nqcne->cq_handle_low); + q_handle |= (u64)le32_to_cpu(nqcne->cq_handle_high) << 32; + if (q_handle == (u64)cq) { + nqcne->cq_handle_low = 0; + nqcne->cq_handle_high = 0; + cq->cnq_events++; + } + } + bnxt_qplib_hwq_incr_cons(nq_hwq->max_elements, &peek_cons, + 1, &peek_flags); + } + spin_unlock_bh(&nq_hwq->lock); +} + +/* + * Wait for receiving all NQEs for this CQ. + * clean_nq is tried 100 times, each time clean_cq + * loops upto budget times. budget is based on the + * number of CQs shared by that NQ. So any NQE from + * CQ would be already in the NQ. + */ +static void __wait_for_all_nqes(struct bnxt_qplib_cq *cq, u16 cnq_events) +{ + u32 retry_cnt = 100; + u16 total_events; + + if (!cnq_events) { + clean_nq(cq); + return; + } + while (retry_cnt--) { + total_events = cq->cnq_events; + + /* Increment total_events by 1 if any CREQ event received with CQ notification */ + if (cq->is_cq_err_event) + total_events++; + + if (cnq_events == total_events) { + dev_dbg(&cq->nq->res->pdev->dev, + "QPLIB: NQ cleanup - Received all NQ events\n"); + return; + } + msleep(1); + clean_nq(cq); + } +} + +static void bnxt_qplib_service_nq(unsigned long data) +{ + struct bnxt_qplib_nq *nq = (struct bnxt_qplib_nq *)data; + struct bnxt_qplib_hwq *nq_hwq = &nq->hwq; + int budget = nq->budget; + struct bnxt_qplib_res *res; + struct bnxt_qplib_cq *cq; + struct pci_dev *pdev; + struct nq_base *nqe; + u32 hw_polled = 0; + u64 q_handle; + u32 type; + + res = nq->res; + pdev = res->pdev; + + spin_lock_bh(&nq_hwq->lock); + /* Service the NQ until empty or budget expired */ + while (budget--) { + nqe = bnxt_qplib_get_qe(nq_hwq, nq_hwq->cons, NULL); + if (!NQE_CMP_VALID(nqe, nq->nq_db.dbinfo.flags)) + break; + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + type = le16_to_cpu(nqe->info10_type) & NQ_BASE_TYPE_MASK; + switch (type) { + case NQ_BASE_TYPE_CQ_NOTIFICATION: + { + struct nq_cn *nqcne = (struct nq_cn *)nqe; + + q_handle = le32_to_cpu(nqcne->cq_handle_low); + q_handle |= (u64)le32_to_cpu(nqcne->cq_handle_high) << 32; + cq = (struct bnxt_qplib_cq *)q_handle; + if (!cq) + break; + cq->toggle = (le16_to_cpu(nqe->info10_type) & NQ_CN_TOGGLE_MASK) >> NQ_CN_TOGGLE_SFT; + cq->dbinfo.toggle = cq->toggle; + bnxt_qplib_armen_db(&cq->dbinfo, + DBC_DBC_TYPE_CQ_ARMENA); + spin_lock_bh(&cq->compl_lock); + atomic_set(&cq->arm_state, 0) ; + if (!nq->cqn_handler(nq, (cq))) + nq->stats.num_cqne_processed++; + else + dev_warn(&pdev->dev, + "QPLIB: cqn - type 0x%x not handled\n", + type); + cq->cnq_events++; + spin_unlock_bh(&cq->compl_lock); + break; + } + case NQ_BASE_TYPE_SRQ_EVENT: + { + struct bnxt_qplib_srq *srq; + struct nq_srq_event *nqsrqe = + (struct nq_srq_event *)nqe; + + q_handle = le32_to_cpu(nqsrqe->srq_handle_low); + q_handle |= (u64)le32_to_cpu(nqsrqe->srq_handle_high) << 32; + srq = (struct bnxt_qplib_srq *)q_handle; + bnxt_qplib_armen_db(&srq->dbinfo, + DBC_DBC_TYPE_SRQ_ARMENA); + if (!nq->srqn_handler(nq, + (struct bnxt_qplib_srq *)q_handle, + nqsrqe->event)) + nq->stats.num_srqne_processed++; + else + dev_warn(&pdev->dev, + "QPLIB: SRQ event 0x%x not handled\n", + nqsrqe->event); + break; + } + default: + dev_warn(&pdev->dev, + "QPLIB: nqe with opcode = 0x%x not handled\n", + type); + break; + } + hw_polled++; + bnxt_qplib_hwq_incr_cons(nq_hwq->max_elements, &nq_hwq->cons, + 1, &nq->nq_db.dbinfo.flags); + } + nqe = bnxt_qplib_get_qe(nq_hwq, nq_hwq->cons, NULL); + if (!NQE_CMP_VALID(nqe, nq->nq_db.dbinfo.flags)) { + nq->stats.num_nq_rearm++; + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true); + } else if (nq->requested) { + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true); + nq->stats.num_tasklet_resched++; + } + dev_dbg(&pdev->dev, "QPLIB: cqn/srqn/dbqn \n"); + if (hw_polled >= 0) + dev_dbg(&pdev->dev, + "QPLIB: serviced %llu/%llu/%llu budget 0x%x reaped 0x%x\n", + nq->stats.num_cqne_processed, nq->stats.num_srqne_processed, + nq->stats.num_dbqne_processed, budget, hw_polled); + dev_dbg(&pdev->dev, + "QPLIB: resched_cnt = %llu arm_count = %llu\n", + nq->stats.num_tasklet_resched, nq->stats.num_nq_rearm); + spin_unlock_bh(&nq_hwq->lock); +} + +static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance) +{ + struct bnxt_qplib_nq *nq = dev_instance; + struct bnxt_qplib_hwq *nq_hwq = &nq->hwq; + u32 sw_cons; + + /* Prefetch the NQ element */ + sw_cons = HWQ_CMP(nq_hwq->cons, nq_hwq); + if (sw_cons >= 0) + prefetch(bnxt_qplib_get_qe(nq_hwq, sw_cons, NULL)); + + bnxt_qplib_service_nq((unsigned long)nq); + + return IRQ_HANDLED; +} + +void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) +{ + struct bnxt_qplib_res *res; + + if (!nq->requested) + return; + + nq->requested = false; + res = nq->res; + /* Mask h/w interrupt */ + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, false); + /* Sync with last running IRQ handler */ + synchronize_irq(nq->msix_vec); + free_irq(nq->msix_vec, nq); + kfree(nq->name); + nq->name = NULL; +} + +void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) +{ + if (nq->cqn_wq) { + destroy_workqueue(nq->cqn_wq); + nq->cqn_wq = NULL; + } + /* Make sure the HW is stopped! */ + bnxt_qplib_nq_stop_irq(nq, true); + + nq->nq_db.reg.bar_reg = NULL; + nq->nq_db.db = NULL; + + nq->cqn_handler = NULL; + nq->srqn_handler = NULL; + nq->msix_vec = 0; +} + +int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, + int msix_vector, bool need_init) +{ + struct bnxt_qplib_res *res; + int rc; + + res = nq->res; + if (nq->requested) + return -EFAULT; + + nq->msix_vec = msix_vector; + nq->name = kasprintf(GFP_KERNEL, "bnxt_re-nq-%d@pci:%s\n", + nq_indx, pci_name(res->pdev)); + if (!nq->name) + return -ENOMEM; + rc = request_irq(nq->msix_vec, bnxt_qplib_nq_irq, 0, nq->name, nq); + if (rc) { + kfree(nq->name); + nq->name = NULL; + return rc; + } + nq->requested = true; + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true); + + return rc; +} + +static void bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt) +{ + struct bnxt_qplib_reg_desc *dbreg; + struct bnxt_qplib_nq_db *nq_db; + struct bnxt_qplib_res *res; + + nq_db = &nq->nq_db; + res = nq->res; + dbreg = &res->dpi_tbl.ucreg; + + nq_db->reg.bar_id = dbreg->bar_id; + nq_db->reg.bar_base = dbreg->bar_base; + nq_db->reg.bar_reg = dbreg->bar_reg + reg_offt; + nq_db->reg.len = _is_chip_gen_p5_p7(res->cctx) ? sizeof(u64) : + sizeof(u32); + + nq_db->dbinfo.db = nq_db->reg.bar_reg; + nq_db->dbinfo.hwq = &nq->hwq; + nq_db->dbinfo.xid = nq->ring_id; + nq_db->dbinfo.seed = nq->ring_id; + nq_db->dbinfo.flags = 0; + spin_lock_init(&nq_db->dbinfo.lock); + nq_db->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + nq_db->dbinfo.res = nq->res; + + return; +} + +int bnxt_qplib_enable_nq(struct bnxt_qplib_nq *nq, int nq_idx, + int msix_vector, int bar_reg_offset, + cqn_handler_t cqn_handler, + srqn_handler_t srqn_handler) +{ + struct pci_dev *pdev; + int rc; + + pdev = nq->res->pdev; + nq->cqn_handler = cqn_handler; + nq->srqn_handler = srqn_handler; + nq->load = 0; + mutex_init(&nq->lock); + + /* Have a task to schedule CQ notifiers in post send case */ + nq->cqn_wq = create_singlethread_workqueue("bnxt_qplib_nq\n"); + if (!nq->cqn_wq) + return -ENOMEM; + + bnxt_qplib_map_nq_db(nq, bar_reg_offset); + rc = bnxt_qplib_nq_start_irq(nq, nq_idx, msix_vector, true); + if (rc) { + dev_err(&pdev->dev, + "QPLIB: Failed to request irq for nq-idx %d\n", nq_idx); + goto fail; + } + dev_dbg(&pdev->dev, "QPLIB: NQ max = 0x%x\n", nq->hwq.max_elements); + + return 0; +fail: + bnxt_qplib_disable_nq(nq); + return rc; +} + +void bnxt_qplib_free_nq_mem(struct bnxt_qplib_nq *nq) +{ + if (nq->hwq.max_elements) { + bnxt_qplib_free_hwq(nq->res, &nq->hwq); + nq->hwq.max_elements = 0; + } +} + +int bnxt_qplib_alloc_nq_mem(struct bnxt_qplib_res *res, + struct bnxt_qplib_nq *nq) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_sg_info sginfo = {}; + + nq->res = res; + if (!nq->hwq.max_elements || + nq->hwq.max_elements > BNXT_QPLIB_NQE_MAX_CNT) + nq->hwq.max_elements = BNXT_QPLIB_NQE_MAX_CNT; + + sginfo.pgsize = PAGE_SIZE; + sginfo.pgshft = PAGE_SHIFT; + hwq_attr.res = res; + hwq_attr.sginfo = &sginfo; + hwq_attr.depth = nq->hwq.max_elements; + hwq_attr.stride = sizeof(struct nq_base); + hwq_attr.type = _get_hwq_type(res); + if (bnxt_qplib_alloc_init_hwq(&nq->hwq, &hwq_attr)) { + dev_err(&res->pdev->dev, "QPLIB: FP NQ allocation failed\n"); + return -ENOMEM; + } + nq->budget = 8; + return 0; +} + +/* SRQ */ +static int __qplib_destroy_srq(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_srq *srq) +{ + struct creq_destroy_srq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_srq req = {}; + /* Configure the request */ + req.srq_cid = cpu_to_le32(srq->id); + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DESTROY_SRQ, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + return bnxt_qplib_rcfw_send_message(rcfw, &msg); +} + +int bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + int rc; + + rc = __qplib_destroy_srq(rcfw, srq); + if (rc) + return rc; + bnxt_qplib_free_hwq(res, &srq->hwq); + kfree(srq->swq); + return 0; +} + +int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_create_srq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_create_srq req = {}; + u16 pg_sz_lvl = 0; + u16 srq_size; + int rc, idx; + + hwq_attr.res = res; + hwq_attr.sginfo = &srq->sginfo; + hwq_attr.depth = srq->max_wqe; + hwq_attr.stride = srq->wqe_size; + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr); + if (rc) + goto exit; + /* Configure the request */ + req.dpi = cpu_to_le32(srq->dpi->dpi); + req.srq_handle = cpu_to_le64((uintptr_t)srq); + srq_size = min_t(u32, srq->hwq.depth, U16_MAX); + req.srq_size = cpu_to_le16(srq_size); + pg_sz_lvl |= (_get_base_pg_size(&srq->hwq) << + CMDQ_CREATE_SRQ_PG_SIZE_SFT); + pg_sz_lvl |= (srq->hwq.level & CMDQ_CREATE_SRQ_LVL_MASK); + req.pg_size_lvl = cpu_to_le16(pg_sz_lvl); + req.pbl = cpu_to_le64(_get_base_addr(&srq->hwq)); + req.pd_id = cpu_to_le32(srq->pd->id); + req.eventq_id = cpu_to_le16(srq->eventq_hw_ring_id); + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_CREATE_SRQ, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail; + if (!srq->is_user) { + srq->swq = kcalloc(srq->hwq.depth, sizeof(*srq->swq), + GFP_KERNEL); + if (!srq->swq) + goto srq_fail; + srq->start_idx = 0; + srq->last_idx = srq->hwq.depth - 1; + for (idx = 0; idx < srq->hwq.depth; idx++) + srq->swq[idx].next_idx = idx + 1; + srq->swq[srq->last_idx].next_idx = -1; + } + + spin_lock_init(&srq->lock); + srq->id = le32_to_cpu(resp.xid); + srq->cctx = res->cctx; + srq->dbinfo.hwq = &srq->hwq; + srq->dbinfo.xid = srq->id; + srq->dbinfo.db = srq->dpi->dbr; + srq->dbinfo.max_slot = 1; + srq->dbinfo.priv_db = res->dpi_tbl.priv_db; + srq->dbinfo.flags = 0; + spin_lock_init(&srq->dbinfo.lock); + srq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + srq->dbinfo.shadow_key_arm_ena = BNXT_QPLIB_DBR_KEY_INVALID; + srq->dbinfo.res = res; + srq->dbinfo.seed = srq->id; + if (srq->threshold) + bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); + srq->arm_req = false; + return 0; +srq_fail: + __qplib_destroy_srq(rcfw, srq); +fail: + bnxt_qplib_free_hwq(res, &srq->hwq); +exit: + return rc; +} + +int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq) +{ + struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; + u32 avail = 0; + + avail = __bnxt_qplib_get_avail(srq_hwq); + if (avail <= srq->threshold) { + srq->arm_req = false; + bnxt_qplib_srq_arm_db(&srq->dbinfo); + } else { + /* Deferred arming */ + srq->arm_req = true; + } + return 0; +} + +int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_query_srq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct creq_query_srq_resp_sb *sb; + struct bnxt_qplib_rcfw_sbuf sbuf; + struct cmdq_query_srq req = {}; + int rc = 0; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_SRQ, + sizeof(req)); + sbuf.size = ALIGN(sizeof(*sb), BNXT_QPLIB_CMDQE_UNITS); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) + return -ENOMEM; + req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; + req.srq_cid = cpu_to_le32(srq->id); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + /* TODO: What to do with the query? */ + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + + return rc; +} + +int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; + struct sq_sge *hw_sge; + struct rq_wqe *srqe; + int i, rc = 0, next; + u32 avail; + + spin_lock(&srq_hwq->lock); + if (srq->start_idx == srq->last_idx) { + dev_err(&srq_hwq->pdev->dev, "QPLIB: FP: SRQ (0x%x) is full!\n", + srq->id); + rc = -EINVAL; + spin_unlock(&srq_hwq->lock); + goto done; + } + next = srq->start_idx; + srq->start_idx = srq->swq[next].next_idx; + spin_unlock(&srq_hwq->lock); + + srqe = bnxt_qplib_get_qe(srq_hwq, srq_hwq->prod, NULL); + memset(srqe, 0, srq->wqe_size); + /* Calculate wqe_size and data_len */ + for (i = 0, hw_sge = (struct sq_sge *)srqe->data; + i < wqe->num_sge; i++, hw_sge++) { + hw_sge->va_or_pa = cpu_to_le64(wqe->sg_list[i].addr); + hw_sge->l_key = cpu_to_le32(wqe->sg_list[i].lkey); + hw_sge->size = cpu_to_le32(wqe->sg_list[i].size); + } + srqe->wqe_type = wqe->type; + srqe->flags = wqe->flags; + srqe->wqe_size = wqe->num_sge + + ((offsetof(typeof(*srqe), data) + 15) >> 4); + if (!wqe->num_sge) + srqe->wqe_size++; + srqe->wr_id |= cpu_to_le32((u32)next); + srq->swq[next].wr_id = wqe->wr_id; + bnxt_qplib_hwq_incr_prod(&srq->dbinfo, srq_hwq, srq->dbinfo.max_slot); + /* retaining srq_hwq->cons for this logic actually the lock is only + * required to read srq_hwq->cons. + */ + spin_lock(&srq_hwq->lock); + avail = __bnxt_qplib_get_avail(srq_hwq); + spin_unlock(&srq_hwq->lock); + /* Ring DB */ + bnxt_qplib_ring_prod_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ); + if (srq->arm_req && avail <= srq->threshold) { + srq->arm_req = false; + bnxt_qplib_srq_arm_db(&srq->dbinfo); + } +done: + return rc; +} + +/* QP */ +static int __qplib_destroy_qp(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_qp *qp) +{ + struct creq_destroy_qp_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_qp req = {}; + + req.qp_cid = cpu_to_le32(qp->id); + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DESTROY_QP, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + return bnxt_qplib_rcfw_send_message(rcfw, &msg); +} + +static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) +{ + int rc = 0; + int indx; + + que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL); + if (!que->swq) { + rc = -ENOMEM; + goto out; + } + + que->swq_start = 0; + que->swq_last = que->max_wqe - 1; + for (indx = 0; indx < que->max_wqe; indx++) + que->swq[indx].next_idx = indx + 1; + que->swq[que->swq_last].next_idx = 0; /* Make it circular */ + que->swq_last = 0; +out: + return rc; +} + +static struct bnxt_qplib_swq *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, + u32 *swq_idx) +{ + u32 idx; + + idx = que->swq_start; + if (swq_idx) + *swq_idx = idx; + return &que->swq[idx]; +} + +static void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx) +{ + que->swq_start = que->swq[idx].next_idx; +} + +static u32 bnxt_qplib_get_stride(void) +{ + return sizeof(struct sq_sge); +} + +static u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que) +{ + u8 stride; + + stride = bnxt_qplib_get_stride(); + return (que->wqe_size * que->max_wqe) / stride; +} + +static u32 _set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode) +{ + /* For Variable mode supply number of 16B slots */ + return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + que->max_wqe : bnxt_qplib_get_depth(que); +} + +static u32 _set_sq_max_slot(u8 wqe_mode) +{ + /* for static mode index divisor is 8 */ + return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + sizeof(struct sq_send) / sizeof(struct sq_sge) : 1; +} + +static u32 _set_rq_max_slot(struct bnxt_qplib_q *que) +{ + return (que->wqe_size / sizeof(struct sq_sge)); +} + +int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_create_qp1_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_q *sq = &qp->sq; + struct bnxt_qplib_q *rq = &qp->rq; + struct cmdq_create_qp1 req = {}; + struct bnxt_qplib_reftbl *tbl; + unsigned long flag; + u8 pg_sz_lvl = 0; + u32 qp_flags = 0; + int rc; + + /* General */ + req.type = qp->type; + req.dpi = cpu_to_le32(qp->dpi->dpi); + req.qp_handle = cpu_to_le64(qp->qp_handle); + /* SQ */ + hwq_attr.res = res; + hwq_attr.sginfo = &sq->sginfo; + hwq_attr.stride = bnxt_qplib_get_stride(); + hwq_attr.depth = bnxt_qplib_get_depth(sq); + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); + if (rc) + goto exit; + + req.sq_size = cpu_to_le32(_set_sq_size(sq, qp->wqe_mode)); + req.sq_pbl = cpu_to_le64(_get_base_addr(&sq->hwq)); + pg_sz_lvl = _get_base_pg_size(&sq->hwq) << + CMDQ_CREATE_QP1_SQ_PG_SIZE_SFT; + pg_sz_lvl |= ((sq->hwq.level & CMDQ_CREATE_QP1_SQ_LVL_MASK) << + CMDQ_CREATE_QP1_SQ_LVL_SFT); + req.sq_pg_size_sq_lvl = pg_sz_lvl; + req.sq_fwo_sq_sge = cpu_to_le16(((0 << CMDQ_CREATE_QP1_SQ_FWO_SFT) & + CMDQ_CREATE_QP1_SQ_FWO_MASK) | + (sq->max_sge & + CMDQ_CREATE_QP1_SQ_SGE_MASK)); + req.scq_cid = cpu_to_le32(qp->scq->id); + + /* RQ */ + if (!qp->srq) { + hwq_attr.res = res; + hwq_attr.sginfo = &rq->sginfo; + hwq_attr.stride = bnxt_qplib_get_stride(); + hwq_attr.depth = bnxt_qplib_get_depth(rq); + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); + if (rc) + goto fail_sq; + req.rq_size = cpu_to_le32(rq->max_wqe); + req.rq_pbl = cpu_to_le64(_get_base_addr(&rq->hwq)); + pg_sz_lvl = _get_base_pg_size(&rq->hwq) << + CMDQ_CREATE_QP1_RQ_PG_SIZE_SFT; + pg_sz_lvl |= ((rq->hwq.level & CMDQ_CREATE_QP1_RQ_LVL_MASK) << + CMDQ_CREATE_QP1_RQ_LVL_SFT); + req.rq_pg_size_rq_lvl = pg_sz_lvl; + req.rq_fwo_rq_sge = + cpu_to_le16(((0 << CMDQ_CREATE_QP1_RQ_FWO_SFT) & + CMDQ_CREATE_QP1_RQ_FWO_MASK) | + (rq->max_sge & + CMDQ_CREATE_QP1_RQ_SGE_MASK)); + } else { + /* SRQ */ + qp_flags |= CMDQ_CREATE_QP1_QP_FLAGS_SRQ_USED; + req.srq_cid = cpu_to_le32(qp->srq->id); + } + req.rcq_cid = cpu_to_le32(qp->rcq->id); + + qp_flags |= CMDQ_CREATE_QP1_QP_FLAGS_RESERVED_LKEY_ENABLE; + req.qp_flags = cpu_to_le32(qp_flags); + req.pd_id = cpu_to_le32(qp->pd->id); + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_CREATE_QP1, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail_rq; + + rc = bnxt_qplib_alloc_init_swq(sq); + if (rc) + goto sq_swq; + + if (!qp->srq) { + rc = bnxt_qplib_alloc_init_swq(rq); + if (rc) + goto rq_swq; + } + + qp->id = le32_to_cpu(resp.xid); + qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; + qp->cctx = res->cctx; + sq->dbinfo.hwq = &sq->hwq; + sq->dbinfo.xid = qp->id; + sq->dbinfo.db = qp->dpi->dbr; + sq->dbinfo.max_slot = _set_sq_max_slot(qp->wqe_mode); + sq->dbinfo.flags = 0; + spin_lock_init(&sq->dbinfo.lock); + sq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + sq->dbinfo.res = res; + if (rq->max_wqe) { + rq->dbinfo.hwq = &rq->hwq; + rq->dbinfo.xid = qp->id; + rq->dbinfo.db = qp->dpi->dbr; + rq->dbinfo.max_slot = _set_rq_max_slot(rq); + rq->dbinfo.flags = 0; + spin_lock_init(&rq->dbinfo.lock); + rq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + rq->dbinfo.res = res; + } + + tbl = &res->reftbl.qpref; + spin_lock_irqsave(&tbl->lock, flag); + tbl->rec[tbl->max].xid = qp->id; + tbl->rec[tbl->max].handle = qp; + spin_unlock_irqrestore(&tbl->lock, flag); + + return 0; +rq_swq: + kfree(sq->swq); +sq_swq: + __qplib_destroy_qp(rcfw, qp); +fail_rq: + bnxt_qplib_free_hwq(res, &rq->hwq); +fail_sq: + bnxt_qplib_free_hwq(res, &sq->hwq); +exit: + return rc; +} + +static void bnxt_qplib_init_psn_ptr(struct bnxt_qplib_qp *qp, int size) +{ + struct bnxt_qplib_hwq *sq_hwq; + struct bnxt_qplib_q *sq; + u64 fpsne, psn_pg; + u16 indx_pad = 0; + + sq = &qp->sq; + sq_hwq = &sq->hwq; + /* First psn entry */ + fpsne = (u64)bnxt_qplib_get_qe(sq_hwq, sq_hwq->depth, &psn_pg); + if (!IS_ALIGNED(fpsne, PAGE_SIZE)) + indx_pad = (fpsne & ~PAGE_MASK) / size; + sq_hwq->pad_pgofft = indx_pad; + sq_hwq->pad_pg = (u64 *)psn_pg; + sq_hwq->pad_stride = size; +} + +int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct bnxt_qplib_sg_info sginfo = {}; + struct creq_create_qp_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_q *sq = &qp->sq; + struct bnxt_qplib_q *rq = &qp->rq; + struct cmdq_create_qp req = {}; + struct bnxt_qplib_reftbl *tbl; + struct bnxt_qplib_hwq *xrrq; + int rc, req_size, psn_sz; + unsigned long flag; + u8 pg_sz_lvl = 0; + u32 qp_flags = 0; + u32 qp_idx; + u16 nsge; + u32 sqsz; + + qp->cctx = res->cctx; + if (res->dattr) + qp->dev_cap_flags = res->dattr->dev_cap_flags; + /* General */ + req.type = qp->type; + req.dpi = cpu_to_le32(qp->dpi->dpi); + req.qp_handle = cpu_to_le64(qp->qp_handle); + + /* SQ */ + if (qp->type == CMDQ_CREATE_QP_TYPE_RC) { + psn_sz = _is_chip_gen_p5_p7(qp->cctx) ? + sizeof(struct sq_psn_search_ext) : + sizeof(struct sq_psn_search); + if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { + psn_sz = sizeof(struct sq_msn_search); + qp->msn = 0; + } + } else { + psn_sz = 0; + } + + hwq_attr.res = res; + hwq_attr.sginfo = &sq->sginfo; + hwq_attr.stride = bnxt_qplib_get_stride(); + hwq_attr.depth = bnxt_qplib_get_depth(sq); + hwq_attr.aux_stride = psn_sz; + hwq_attr.aux_depth = (psn_sz) ? + _set_sq_size(sq, qp->wqe_mode) : 0; + /* Update msn tbl size */ + if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) { + if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) + hwq_attr.aux_depth = roundup_pow_of_two(_set_sq_size(sq, qp->wqe_mode)); + else + hwq_attr.aux_depth = roundup_pow_of_two(_set_sq_size(sq, qp->wqe_mode)) / 2; + qp->msn_tbl_sz = hwq_attr.aux_depth; + qp->msn = 0; + } + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); + if (rc) + goto exit; + + sqsz = _set_sq_size(sq, qp->wqe_mode); + /* 0xffff is the max sq size hw limits to */ + if (sqsz > BNXT_QPLIB_MAX_SQSZ) { + pr_err("QPLIB: FP: QP (0x%x) exceeds sq size %d\n", qp->id, sqsz); + goto fail_sq; + } + req.sq_size = cpu_to_le32(sqsz); + req.sq_pbl = cpu_to_le64(_get_base_addr(&sq->hwq)); + pg_sz_lvl = _get_base_pg_size(&sq->hwq) << + CMDQ_CREATE_QP_SQ_PG_SIZE_SFT; + pg_sz_lvl |= ((sq->hwq.level & CMDQ_CREATE_QP_SQ_LVL_MASK) << + CMDQ_CREATE_QP_SQ_LVL_SFT); + req.sq_pg_size_sq_lvl = pg_sz_lvl; + req.sq_fwo_sq_sge = cpu_to_le16(((0 << CMDQ_CREATE_QP_SQ_FWO_SFT) & + CMDQ_CREATE_QP_SQ_FWO_MASK) | + ((BNXT_RE_HW_RETX(qp->dev_cap_flags)) ? + BNXT_MSN_TBLE_SGE : sq->max_sge & + CMDQ_CREATE_QP_SQ_SGE_MASK)); + req.scq_cid = cpu_to_le32(qp->scq->id); + + /* RQ/SRQ */ + if (!qp->srq) { + hwq_attr.res = res; + hwq_attr.sginfo = &rq->sginfo; + hwq_attr.stride = bnxt_qplib_get_stride(); + hwq_attr.depth = bnxt_qplib_get_depth(rq); + hwq_attr.aux_stride = 0; + hwq_attr.aux_depth = 0; + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); + if (rc) + goto fail_sq; + req.rq_size = cpu_to_le32(rq->max_wqe); + req.rq_pbl = cpu_to_le64(_get_base_addr(&rq->hwq)); + pg_sz_lvl = _get_base_pg_size(&rq->hwq) << + CMDQ_CREATE_QP_RQ_PG_SIZE_SFT; + pg_sz_lvl |= ((rq->hwq.level & CMDQ_CREATE_QP_RQ_LVL_MASK) << + CMDQ_CREATE_QP_RQ_LVL_SFT); + req.rq_pg_size_rq_lvl = pg_sz_lvl; + nsge = (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + res->dattr->max_qp_sges : rq->max_sge; + req.rq_fwo_rq_sge = + cpu_to_le16(((0 << CMDQ_CREATE_QP_RQ_FWO_SFT) & + CMDQ_CREATE_QP_RQ_FWO_MASK) | + (nsge & CMDQ_CREATE_QP_RQ_SGE_MASK)); + } else { + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_SRQ_USED; + req.srq_cid = cpu_to_le32(qp->srq->id); + } + req.rcq_cid = cpu_to_le32(qp->rcq->id); + + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_RESERVED_LKEY_ENABLE; + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FR_PMR_ENABLED; + if (qp->sig_type) + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION; + if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED; + if (res->cctx->modes.te_bypass) + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_OPTIMIZED_TRANSMIT_ENABLED; + if (res->dattr && + bnxt_ext_stats_supported(qp->cctx, res->dattr->dev_cap_flags, res->is_vf)) + qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED; + req.qp_flags = cpu_to_le32(qp_flags); + + /* ORRQ and IRRQ */ + if (psn_sz) { + xrrq = &qp->orrq; + xrrq->max_elements = + ORD_LIMIT_TO_ORRQ_SLOTS(qp->max_rd_atomic); + req_size = xrrq->max_elements * + BNXT_QPLIB_MAX_ORRQE_ENTRY_SIZE + PAGE_SIZE - 1; + req_size &= ~(PAGE_SIZE - 1); + sginfo.pgsize = req_size; + sginfo.pgshft = PAGE_SHIFT; + + hwq_attr.res = res; + hwq_attr.sginfo = &sginfo; + hwq_attr.depth = xrrq->max_elements; + hwq_attr.stride = BNXT_QPLIB_MAX_ORRQE_ENTRY_SIZE; + hwq_attr.aux_stride = 0; + hwq_attr.aux_depth = 0; + hwq_attr.type = HWQ_TYPE_CTX; + rc = bnxt_qplib_alloc_init_hwq(xrrq, &hwq_attr); + if (rc) + goto fail_rq; + req.orrq_addr = cpu_to_le64(_get_base_addr(xrrq)); + + xrrq = &qp->irrq; + xrrq->max_elements = IRD_LIMIT_TO_IRRQ_SLOTS( + qp->max_dest_rd_atomic); + req_size = xrrq->max_elements * + BNXT_QPLIB_MAX_IRRQE_ENTRY_SIZE + PAGE_SIZE - 1; + req_size &= ~(PAGE_SIZE - 1); + sginfo.pgsize = req_size; + hwq_attr.depth = xrrq->max_elements; + hwq_attr.stride = BNXT_QPLIB_MAX_IRRQE_ENTRY_SIZE; + rc = bnxt_qplib_alloc_init_hwq(xrrq, &hwq_attr); + if (rc) + goto fail_orrq; + req.irrq_addr = cpu_to_le64(_get_base_addr(xrrq)); + } + req.pd_id = cpu_to_le32(qp->pd->id); + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_CREATE_QP, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail; + + if (!qp->is_user) { + rc = bnxt_qplib_alloc_init_swq(sq); + if (rc) + goto swq_sq; + if (!qp->srq) { + rc = bnxt_qplib_alloc_init_swq(rq); + if (rc) + goto swq_rq; + } + if (psn_sz) + bnxt_qplib_init_psn_ptr(qp, psn_sz); + } + qp->id = le32_to_cpu(resp.xid); + qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; + INIT_LIST_HEAD(&qp->sq_flush); + INIT_LIST_HEAD(&qp->rq_flush); + + sq->dbinfo.hwq = &sq->hwq; + sq->dbinfo.xid = qp->id; + sq->dbinfo.db = qp->dpi->dbr; + sq->dbinfo.max_slot = _set_sq_max_slot(qp->wqe_mode); + sq->dbinfo.flags = 0; + spin_lock_init(&sq->dbinfo.lock); + sq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + sq->dbinfo.res = res; + sq->dbinfo.seed = qp->id; + if (rq->max_wqe) { + rq->dbinfo.hwq = &rq->hwq; + rq->dbinfo.xid = qp->id; + rq->dbinfo.db = qp->dpi->dbr; + rq->dbinfo.max_slot = _set_rq_max_slot(rq); + rq->dbinfo.flags = 0; + spin_lock_init(&rq->dbinfo.lock); + rq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + rq->dbinfo.res = res; + rq->dbinfo.seed = qp->id; + } + + tbl = &res->reftbl.qpref; + qp_idx = map_qp_id_to_tbl_indx(qp->id, tbl); + spin_lock_irqsave(&tbl->lock, flag); + tbl->rec[qp_idx].xid = qp->id; + tbl->rec[qp_idx].handle = qp; + spin_unlock_irqrestore(&tbl->lock, flag); + + return 0; +swq_rq: + kfree(sq->swq); +swq_sq: + __qplib_destroy_qp(rcfw, qp); +fail: + bnxt_qplib_free_hwq(res, &qp->irrq); +fail_orrq: + bnxt_qplib_free_hwq(res, &qp->orrq); +fail_rq: + bnxt_qplib_free_hwq(res, &rq->hwq); +fail_sq: + bnxt_qplib_free_hwq(res, &sq->hwq); +exit: + return rc; +} + +static void __filter_modify_flags(struct bnxt_qplib_qp *qp) +{ + switch (qp->cur_qp_state) { + case CMDQ_MODIFY_QP_NEW_STATE_RESET: + switch (qp->state) { + case CMDQ_MODIFY_QP_NEW_STATE_INIT: + break; + default: + break; + } + break; + case CMDQ_MODIFY_QP_NEW_STATE_INIT: + switch (qp->state) { + case CMDQ_MODIFY_QP_NEW_STATE_RTR: + if (!(qp->modify_flags & + CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU)) { + qp->modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU; + qp->path_mtu = CMDQ_MODIFY_QP_PATH_MTU_MTU_2048; + } + qp->modify_flags &= + ~CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID; + /* Bono FW requires the max_dest_rd_atomic to be >= 1 */ + if (qp->max_dest_rd_atomic < 1) + qp->max_dest_rd_atomic = 1; + qp->modify_flags &= ~CMDQ_MODIFY_QP_MODIFY_MASK_SRC_MAC; + /* Bono FW 20.6.5 requires SGID_INDEX to be configured */ + if (!(qp->modify_flags & + CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX)) { + qp->modify_flags |= + CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX; + qp->ah.sgid_index = 0; + } + break; + default: + break; + } + break; + case CMDQ_MODIFY_QP_NEW_STATE_RTR: + switch (qp->state) { + case CMDQ_MODIFY_QP_NEW_STATE_RTS: + /* Bono FW requires the max_rd_atomic to be >= 1 */ + if (qp->max_rd_atomic < 1) + qp->max_rd_atomic = 1; + qp->modify_flags &= + ~(CMDQ_MODIFY_QP_MODIFY_MASK_PKEY | + CMDQ_MODIFY_QP_MODIFY_MASK_DGID | + CMDQ_MODIFY_QP_MODIFY_MASK_FLOW_LABEL | + CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX | + CMDQ_MODIFY_QP_MODIFY_MASK_HOP_LIMIT | + CMDQ_MODIFY_QP_MODIFY_MASK_TRAFFIC_CLASS | + CMDQ_MODIFY_QP_MODIFY_MASK_DEST_MAC | + CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU | + CMDQ_MODIFY_QP_MODIFY_MASK_RQ_PSN | + CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER | + CMDQ_MODIFY_QP_MODIFY_MASK_MAX_DEST_RD_ATOMIC | + CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID); + break; + default: + break; + } + break; + case CMDQ_MODIFY_QP_NEW_STATE_RTS: + break; + case CMDQ_MODIFY_QP_NEW_STATE_SQD: + break; + case CMDQ_MODIFY_QP_NEW_STATE_SQE: + break; + case CMDQ_MODIFY_QP_NEW_STATE_ERR: + break; + default: + break; + } +} + +int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_modify_qp_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_modify_qp req = {}; + bool ppp_requested = false; + u32 temp32[4]; + u32 bmask; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_MODIFY_QP, + sizeof(req)); + + /* Filter out the qp_attr_mask based on the state->new transition */ + __filter_modify_flags(qp); + bmask = qp->modify_flags; + req.modify_mask = cpu_to_le32(qp->modify_flags); + req.qp_cid = cpu_to_le32(qp->id); + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_STATE) { + req.network_type_en_sqd_async_notify_new_state = + (qp->state & CMDQ_MODIFY_QP_NEW_STATE_MASK) | + (qp->en_sqd_async_notify == true ? + CMDQ_MODIFY_QP_EN_SQD_ASYNC_NOTIFY : 0); + if (__can_request_ppp(qp)) { + req.path_mtu_pingpong_push_enable = + CMDQ_MODIFY_QP_PINGPONG_PUSH_ENABLE; + req.pingpong_push_dpi = qp->ppp.dpi; + ppp_requested = true; + } + } + req.network_type_en_sqd_async_notify_new_state |= qp->nw_type; + + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS) { + req.access = qp->access; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_PKEY) + req.pkey = IB_DEFAULT_PKEY_FULL; + + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_QKEY) { + req.qkey = cpu_to_le32(qp->qkey); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_DGID) { + memcpy(temp32, qp->ah.dgid.data, sizeof(struct bnxt_qplib_gid)); + req.dgid[0] = cpu_to_le32(temp32[0]); + req.dgid[1] = cpu_to_le32(temp32[1]); + req.dgid[2] = cpu_to_le32(temp32[2]); + req.dgid[3] = cpu_to_le32(temp32[3]); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_FLOW_LABEL) { + req.flow_label = cpu_to_le32(qp->ah.flow_label); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_SGID_INDEX) { + req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[qp->ah.sgid_index]); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_HOP_LIMIT) { + req.hop_limit = qp->ah.hop_limit; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_TRAFFIC_CLASS) { + req.traffic_class = qp->ah.traffic_class; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_DEST_MAC) { + memcpy(req.dest_mac, qp->ah.dmac, 6); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU) { + req.path_mtu_pingpong_push_enable = qp->path_mtu; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_TIMEOUT) { + req.timeout = qp->timeout; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_RETRY_CNT) { + req.retry_cnt = qp->retry_cnt; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_RNR_RETRY) { + req.rnr_retry = qp->rnr_retry; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER) { + req.min_rnr_timer = qp->min_rnr_timer; + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_RQ_PSN) { + req.rq_psn = cpu_to_le32(qp->rq.psn); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_SQ_PSN) { + req.sq_psn = cpu_to_le32(qp->sq.psn); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_MAX_RD_ATOMIC) { + req.max_rd_atomic = + ORD_LIMIT_TO_ORRQ_SLOTS(qp->max_rd_atomic); + } + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_MAX_DEST_RD_ATOMIC) { + req.max_dest_rd_atomic = + IRD_LIMIT_TO_IRRQ_SLOTS(qp->max_dest_rd_atomic); + } + req.sq_size = cpu_to_le32(qp->sq.hwq.max_elements); + req.rq_size = cpu_to_le32(qp->rq.hwq.max_elements); + req.sq_sge = cpu_to_le16(qp->sq.max_sge); + req.rq_sge = cpu_to_le16(qp->rq.max_sge); + req.max_inline_data = cpu_to_le32(qp->max_inline_data); + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID) + req.dest_qp_id = cpu_to_le32(qp->dest_qpn); + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_ENABLE_CC) + req.enable_cc = cpu_to_le16(CMDQ_MODIFY_QP_ENABLE_CC); + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_TOS_ECN) + req.tos_dscp_tos_ecn = + ((qp->tos_ecn << CMDQ_MODIFY_QP_TOS_ECN_SFT) & + CMDQ_MODIFY_QP_TOS_ECN_MASK); + if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_TOS_DSCP) + req.tos_dscp_tos_ecn |= + ((qp->tos_dscp << CMDQ_MODIFY_QP_TOS_DSCP_SFT) & + CMDQ_MODIFY_QP_TOS_DSCP_MASK); + req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + msg.qp_state = qp->state; + + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc == -ETIMEDOUT && (qp->state == CMDQ_MODIFY_QP_NEW_STATE_ERR)) { + qp->cur_qp_state = qp->state; + return 0; + } else if (rc) { + return rc; + } + if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_RTR) + qp->lag_src_mac = be32_to_cpu(resp.lag_src_mac); + + if (ppp_requested) + qp->ppp.st_idx_en = resp.pingpong_push_state_index_enabled; + + qp->cur_qp_state = qp->state; + return 0; +} + +int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_query_qp_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_rcfw_sbuf sbuf; + struct creq_query_qp_resp_sb *sb; + struct cmdq_query_qp req = {}; + u32 temp32[4]; + int i, rc; + + sbuf.size = ALIGN(sizeof(*sb), BNXT_QPLIB_CMDQE_UNITS); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) + return -ENOMEM; + sb = sbuf.sb; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_QP, + sizeof(req)); + req.qp_cid = cpu_to_le32(qp->id); + req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto bail; + + /* Extract the context from the side buffer */ + qp->state = sb->en_sqd_async_notify_state & + CREQ_QUERY_QP_RESP_SB_STATE_MASK; + qp->cur_qp_state = qp->state; + qp->en_sqd_async_notify = sb->en_sqd_async_notify_state & + CREQ_QUERY_QP_RESP_SB_EN_SQD_ASYNC_NOTIFY ? + true : false; + qp->access = sb->access; + qp->pkey_index = le16_to_cpu(sb->pkey); + qp->qkey = le32_to_cpu(sb->qkey); + + temp32[0] = le32_to_cpu(sb->dgid[0]); + temp32[1] = le32_to_cpu(sb->dgid[1]); + temp32[2] = le32_to_cpu(sb->dgid[2]); + temp32[3] = le32_to_cpu(sb->dgid[3]); + memcpy(qp->ah.dgid.data, temp32, sizeof(qp->ah.dgid.data)); + + qp->ah.flow_label = le32_to_cpu(sb->flow_label); + + qp->ah.sgid_index = 0; + for (i = 0; i < res->sgid_tbl.max; i++) { + if (res->sgid_tbl.hw_id[i] == le16_to_cpu(sb->sgid_index)) { + qp->ah.sgid_index = i; + break; + } + } + if (i == res->sgid_tbl.max) + dev_dbg(&res->pdev->dev, + "QPLIB: SGID not found qp->id = 0x%x sgid_index = 0x%x\n", + qp->id, le16_to_cpu(sb->sgid_index)); + + qp->ah.hop_limit = sb->hop_limit; + qp->ah.traffic_class = sb->traffic_class; + memcpy(qp->ah.dmac, sb->dest_mac, ETH_ALEN); + qp->ah.vlan_id = le16_to_cpu(sb->path_mtu_dest_vlan_id) & + CREQ_QUERY_QP_RESP_SB_VLAN_ID_MASK >> + CREQ_QUERY_QP_RESP_SB_VLAN_ID_SFT; + qp->path_mtu = le16_to_cpu(sb->path_mtu_dest_vlan_id) & + CREQ_QUERY_QP_RESP_SB_PATH_MTU_MASK; + qp->timeout = sb->timeout; + qp->retry_cnt = sb->retry_cnt; + qp->rnr_retry = sb->rnr_retry; + qp->min_rnr_timer = sb->min_rnr_timer; + qp->rq.psn = le32_to_cpu(sb->rq_psn); + qp->max_rd_atomic = ORRQ_SLOTS_TO_ORD_LIMIT(sb->max_rd_atomic); + qp->sq.psn = le32_to_cpu(sb->sq_psn); + qp->max_dest_rd_atomic = + IRRQ_SLOTS_TO_IRD_LIMIT(sb->max_dest_rd_atomic); + qp->sq.max_wqe = qp->sq.hwq.max_elements; + qp->rq.max_wqe = qp->rq.hwq.max_elements; + qp->sq.max_sge = le16_to_cpu(sb->sq_sge); + qp->rq.max_sge = le16_to_cpu(sb->rq_sge); + qp->max_inline_data = le32_to_cpu(sb->max_inline_data); + qp->dest_qpn = le32_to_cpu(sb->dest_qp_id); + memcpy(qp->smac, sb->src_mac, ETH_ALEN); + qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id); + qp->port_id = le16_to_cpu(sb->port_id); +bail: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + return rc; +} + + +static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp) +{ + struct bnxt_qplib_hwq *cq_hwq = &cq->hwq; + u32 peek_flags, peek_cons; + struct cq_base *hw_cqe; + int i; + + peek_flags = cq->dbinfo.flags; + peek_cons = cq_hwq->cons; + for (i = 0; i < cq_hwq->depth; i++) { + hw_cqe = bnxt_qplib_get_qe(cq_hwq, peek_cons, NULL); + if (CQE_CMP_VALID(hw_cqe, peek_flags)) { + dma_rmb(); + switch (hw_cqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK) { + case CQ_BASE_CQE_TYPE_REQ: + case CQ_BASE_CQE_TYPE_TERMINAL: + { + struct cq_req *cqe = (struct cq_req *)hw_cqe; + + if (qp == le64_to_cpu(cqe->qp_handle)) + cqe->qp_handle = 0; + break; + } + case CQ_BASE_CQE_TYPE_RES_RC: + case CQ_BASE_CQE_TYPE_RES_UD: + case CQ_BASE_CQE_TYPE_RES_RAWETH_QP1: + { + struct cq_res_rc *cqe = (struct cq_res_rc *)hw_cqe; + + if (qp == le64_to_cpu(cqe->qp_handle)) + cqe->qp_handle = 0; + break; + } + default: + break; + } + } + bnxt_qplib_hwq_incr_cons(cq_hwq->depth, &peek_cons, + 1, &peek_flags); + } +} + +int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct bnxt_qplib_reftbl *tbl; + unsigned long flags; + u32 qp_idx; + int rc; + + tbl = &res->reftbl.qpref; + qp_idx = map_qp_id_to_tbl_indx(qp->id, tbl); + spin_lock_irqsave(&tbl->lock, flags); + tbl->rec[qp_idx].xid = BNXT_QPLIB_QP_ID_INVALID; + tbl->rec[qp_idx].handle = NULL; + spin_unlock_irqrestore(&tbl->lock, flags); + + rc = __qplib_destroy_qp(rcfw, qp); + if (rc) { + spin_lock_irqsave(&tbl->lock, flags); + tbl->rec[qp_idx].xid = qp->id; + tbl->rec[qp_idx].handle = qp; + spin_unlock_irqrestore(&tbl->lock, flags); + return rc; + } + + return 0; +} + +void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp) +{ + if (qp->irrq.max_elements) + bnxt_qplib_free_hwq(res, &qp->irrq); + if (qp->orrq.max_elements) + bnxt_qplib_free_hwq(res, &qp->orrq); + + if (!qp->is_user) + kfree(qp->rq.swq); + bnxt_qplib_free_hwq(res, &qp->rq.hwq); + + if (!qp->is_user) + kfree(qp->sq.swq); + bnxt_qplib_free_hwq(res, &qp->sq.hwq); +} + +void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_sge *sge) +{ + struct bnxt_qplib_q *sq = &qp->sq; + struct bnxt_qplib_hdrbuf *buf; + u32 sw_prod; + + memset(sge, 0, sizeof(*sge)); + + buf = qp->sq_hdr_buf; + if (buf) { + sw_prod = sq->swq_start; + sge->addr = (dma_addr_t)(buf->dma_map + sw_prod * buf->step); + sge->lkey = 0xFFFFFFFF; + sge->size = buf->step; + return buf->va + sw_prod * sge->size; + } + return NULL; +} + +u32 bnxt_qplib_get_rq_prod_index(struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_q *rq = &qp->rq; + + return rq->swq_start; +} + +void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_sge *sge) +{ + struct bnxt_qplib_q *rq = &qp->rq; + struct bnxt_qplib_hdrbuf *buf; + u32 sw_prod; + + memset(sge, 0, sizeof(*sge)); + + buf = qp->rq_hdr_buf; + if (buf) { + sw_prod = rq->swq_start; + sge->addr = (dma_addr_t)(buf->dma_map + sw_prod * buf->step); + sge->lkey = 0xFFFFFFFF; + sge->size = buf->step; + return buf->va + sw_prod * sge->size; + } + return NULL; +} + +/* Fil the MSN table into the next psn row */ +static void bnxt_qplib_fill_msn_search(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, + struct bnxt_qplib_swq *swq) +{ + struct sq_msn_search *msns; + u32 start_psn, next_psn; + u16 start_idx; + + msns = (struct sq_msn_search *)swq->psn_search; + msns->start_idx_next_psn_start_psn = 0; + + start_psn = swq->start_psn; + next_psn = swq->next_psn; + start_idx = swq->slot_idx; + msns->start_idx_next_psn_start_psn |= + bnxt_re_update_msn_tbl(start_idx, next_psn, start_psn); + pr_debug("QP_LIB MSN %d START_IDX %u NEXT_PSN %u START_PSN %u\n", + qp->msn, + (u16) + cpu_to_le16(BNXT_RE_MSN_IDX(msns->start_idx_next_psn_start_psn)), + (u32) + cpu_to_le32(BNXT_RE_MSN_NPSN(msns->start_idx_next_psn_start_psn)), + (u32) + cpu_to_le32(BNXT_RE_MSN_SPSN(msns->start_idx_next_psn_start_psn))); + qp->msn++; + qp->msn %= qp->msn_tbl_sz; +} + +static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, + struct bnxt_qplib_swq *swq) +{ + struct sq_psn_search_ext *psns_ext; + struct sq_psn_search *psns; + u32 flg_npsn; + u32 op_spsn; + + if (!swq->psn_search) + return; + + /* Handle MSN differently on cap flags */ + if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { + bnxt_qplib_fill_msn_search(qp, wqe, swq); + return; + } + psns = (struct sq_psn_search *)swq->psn_search; + psns_ext = (struct sq_psn_search_ext *)swq->psn_search; + + op_spsn = ((swq->start_psn << SQ_PSN_SEARCH_START_PSN_SFT) & + SQ_PSN_SEARCH_START_PSN_MASK); + op_spsn |= ((wqe->type << SQ_PSN_SEARCH_OPCODE_SFT) & + SQ_PSN_SEARCH_OPCODE_MASK); + flg_npsn = ((swq->next_psn << SQ_PSN_SEARCH_NEXT_PSN_SFT) & + SQ_PSN_SEARCH_NEXT_PSN_MASK); + + if (_is_chip_gen_p5_p7(qp->cctx)) { + psns_ext->opcode_start_psn = cpu_to_le32(op_spsn); + psns_ext->flags_next_psn = cpu_to_le32(flg_npsn); + psns_ext->start_slot_idx = cpu_to_le16(swq->slot_idx); + } else { + psns->opcode_start_psn = cpu_to_le32(op_spsn); + psns->flags_next_psn = cpu_to_le32(flg_npsn); + } +} + +static u16 _calc_ilsize(struct bnxt_qplib_swqe *wqe) +{ + u16 size = 0; + int indx; + + for (indx = 0; indx < wqe->num_sge; indx++) + size += wqe->sg_list[indx].size; + return size; +} + +static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, + u32 *sw_prod) +{ + struct bnxt_qplib_hwq *sq_hwq; + int len, t_len, offt = 0; + int t_cplen = 0, cplen; + bool pull_dst = true; + void *il_dst = NULL; + void *il_src = NULL; + int indx; + + sq_hwq = &qp->sq.hwq; + t_len = 0; + for (indx = 0; indx < wqe->num_sge; indx++) { + len = wqe->sg_list[indx].size; + il_src = (void *)wqe->sg_list[indx].addr; + t_len += len; + if (t_len > qp->max_inline_data) + goto bad; + while (len) { + if (pull_dst) { + pull_dst = false; + il_dst = bnxt_qplib_get_qe(sq_hwq, ((*sw_prod) % + sq_hwq->depth), NULL); + (*sw_prod)++; + t_cplen = 0; + offt = 0; + } + cplen = min_t(int, len, sizeof(struct sq_sge)); + cplen = min_t(int, cplen, + (sizeof(struct sq_sge) - offt)); + memcpy(il_dst, il_src, cplen); + t_cplen += cplen; + il_src += cplen; + il_dst += cplen; + offt += cplen; + len -= cplen; + if (t_cplen == sizeof(struct sq_sge)) + pull_dst = true; + } + } + + return t_len; +bad: + return -ENOMEM; +} + +static int bnxt_qplib_put_sges(struct bnxt_qplib_hwq *sq_hwq, + struct bnxt_qplib_sge *ssge, + u32 nsge, u32 *sw_prod) +{ + struct sq_sge *dsge; + int indx, len = 0; + + for (indx = 0; indx < nsge; indx++, (*sw_prod)++) { + dsge = bnxt_qplib_get_qe(sq_hwq, ((*sw_prod) % sq_hwq->depth), NULL); + dsge->va_or_pa = cpu_to_le64(ssge[indx].addr); + dsge->l_key = cpu_to_le32(ssge[indx].lkey); + dsge->size = cpu_to_le32(ssge[indx].size); + len += ssge[indx].size; + } + return len; +} + +static u16 _calculate_wqe_byte(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe, u16 *wqe_byte) +{ + u16 wqe_size; + u32 ilsize; + u16 nsge; + + nsge = wqe->num_sge; + if (wqe->flags & BNXT_QPLIB_SWQE_FLAGS_INLINE) { + ilsize = _calc_ilsize(wqe); + wqe_size = (ilsize > qp->max_inline_data) ? + qp->max_inline_data : ilsize; + wqe_size = ALIGN(wqe_size, sizeof(struct sq_sge)); + } else { + wqe_size = nsge * sizeof(struct sq_sge); + } + /* Adding sq_send_hdr is a misnomer, for rq also hdr size is same. */ + wqe_size += sizeof(struct sq_send_hdr); + if (wqe_byte) + *wqe_byte = wqe_size; + return wqe_size / sizeof(struct sq_sge); +} + +static u16 _translate_q_full_delta(struct bnxt_qplib_q *que, u16 wqe_bytes) +{ + /* For Cu/Wh delta = 128, stride = 16, wqe_bytes = 128 + * For Gen-p5 B/C mode delta = 0, stride = 16, wqe_bytes = 128. + * For Gen-p5 delta = 0, stride = 16, 32 <= wqe_bytes <= 512. + * when 8916 is disabled. + */ + return (que->q_full_delta * wqe_bytes) / que->hwq.element_size; +} + +static void bnxt_qplib_pull_psn_buff(struct bnxt_qplib_qp *qp, struct bnxt_qplib_q *sq, + struct bnxt_qplib_swq *swq, bool hw_retx) +{ + struct bnxt_qplib_hwq *sq_hwq; + u32 pg_num, pg_indx; + void *buff; + u32 tail; + + sq_hwq = &sq->hwq; + if (!sq_hwq->pad_pg) + return; + + tail = swq->slot_idx / sq->dbinfo.max_slot; + if (hw_retx) + tail %= qp->msn_tbl_sz; + pg_num = (tail + sq_hwq->pad_pgofft) / (PAGE_SIZE / sq_hwq->pad_stride); + pg_indx = (tail + sq_hwq->pad_pgofft) % (PAGE_SIZE / sq_hwq->pad_stride); + buff = (void *)(sq_hwq->pad_pg[pg_num] + pg_indx * sq_hwq->pad_stride); + /* the start ptr for buff is same ie after the SQ */ + swq->psn_search = buff; +} + +void bnxt_qplib_post_send_db(struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_q *sq = &qp->sq; + + bnxt_qplib_ring_prod_db(&sq->dbinfo, DBC_DBC_TYPE_SQ); +} + +int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_qplib_nq_work *nq_work = NULL; + int i, rc = 0, data_len = 0, pkt_num = 0; + struct bnxt_qplib_q *sq = &qp->sq; + struct bnxt_qplib_hwq *sq_hwq; + struct bnxt_qplib_swq *swq; + bool sch_handler = false; + u16 slots_needed; + void *base_hdr; + void *ext_hdr; + __le32 temp32; + u16 qfd_slots; + u8 wqe_slots; + u16 wqe_size; + u32 sw_prod; + u32 wqe_idx; + + sq_hwq = &sq->hwq; + if (qp->state != CMDQ_MODIFY_QP_NEW_STATE_RTS && + qp->state != CMDQ_MODIFY_QP_NEW_STATE_ERR) { + dev_err(&sq_hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) is in the 0x%x state\n", + qp->id, qp->state); + rc = -EINVAL; + goto done; + } + + wqe_slots = _calculate_wqe_byte(qp, wqe, &wqe_size); + slots_needed = (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + sq->dbinfo.max_slot : wqe_slots; + qfd_slots = _translate_q_full_delta(sq, wqe_size); + if (bnxt_qplib_queue_full(sq_hwq, (slots_needed + qfd_slots))) { + dev_err(&sq_hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) SQ is full!\n", qp->id); + dev_err(&sq_hwq->pdev->dev, + "QPLIB: prod = %#x cons = %#x qdepth = %#x delta = %#x slots = %#x\n", + HWQ_CMP(sq_hwq->prod, sq_hwq), + HWQ_CMP(sq_hwq->cons, sq_hwq), + sq_hwq->max_elements, qfd_slots, slots_needed); + dev_err(&sq_hwq->pdev->dev, + "QPLIB: phantom_wqe_cnt: %d phantom_cqe_cnt: %d\n", + sq->phantom_wqe_cnt, sq->phantom_cqe_cnt); + rc = -ENOMEM; + goto done; + } + + sw_prod = sq_hwq->prod; + swq = bnxt_qplib_get_swqe(sq, &wqe_idx); + swq->slot_idx = sw_prod; + bnxt_qplib_pull_psn_buff(qp, sq, swq, BNXT_RE_HW_RETX(qp->dev_cap_flags)); + + swq->wr_id = wqe->wr_id; + swq->type = wqe->type; + swq->flags = wqe->flags; + swq->slots = slots_needed; + swq->start_psn = sq->psn & BTH_PSN_MASK; + if (qp->sig_type || wqe->flags & BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP) + swq->flags |= SQ_SEND_FLAGS_SIGNAL_COMP; + + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: QP(0x%x) post SQ wr_id[%d] = 0x%llx\n", + qp->id, wqe_idx, swq->wr_id); + if (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { + sch_handler = true; + dev_dbg(&sq_hwq->pdev->dev, + "%s Error QP. Scheduling for poll_cq\n", __func__); + goto queue_err; + } + + base_hdr = bnxt_qplib_get_qe(sq_hwq, sw_prod, NULL); + sw_prod++; + ext_hdr = bnxt_qplib_get_qe(sq_hwq, (sw_prod % sq_hwq->depth), NULL); + sw_prod++; + memset(base_hdr, 0, sizeof(struct sq_sge)); + memset(ext_hdr, 0, sizeof(struct sq_sge)); + + if (wqe->flags & BNXT_QPLIB_SWQE_FLAGS_INLINE) + data_len = bnxt_qplib_put_inline(qp, wqe, &sw_prod); + else + data_len = bnxt_qplib_put_sges(sq_hwq, wqe->sg_list, + wqe->num_sge, &sw_prod); + if (data_len < 0) + goto queue_err; + /* Specifics */ + switch (wqe->type) { + case BNXT_QPLIB_SWQE_TYPE_SEND: + if (qp->type == CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE || + qp->type == CMDQ_CREATE_QP1_TYPE_GSI) { + /* Assemble info for Raw Ethertype QPs */ + struct sq_send_raweth_qp1_hdr *sqe = base_hdr; + struct sq_raw_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->wqe_size = wqe_slots; + sqe->cfa_action = cpu_to_le16(wqe->rawqp1.cfa_action); + sqe->lflags = cpu_to_le16(wqe->rawqp1.lflags); + sqe->length = cpu_to_le32(data_len); + ext_sqe->cfa_meta = cpu_to_le32((wqe->rawqp1.cfa_meta & + SQ_SEND_RAWETH_QP1_CFA_META_VLAN_VID_MASK) << + SQ_SEND_RAWETH_QP1_CFA_META_VLAN_VID_SFT); + + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: RAW/QP1 Send WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\twqe_size = 0x%x\n" + "\tlflags = 0x%x\n" + "\tcfa_action = 0x%x\n" + "\tlength = 0x%x\n" + "\tcfa_meta = 0x%x\n", + sqe->wqe_type, sqe->flags, sqe->wqe_size, + sqe->lflags, sqe->cfa_action, + sqe->length, ext_sqe->cfa_meta); + break; + } + fallthrough; + case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM: + fallthrough; + case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV: + { + struct sq_send_hdr *sqe = base_hdr; + struct sq_ud_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->wqe_size = wqe_slots; + sqe->inv_key_or_imm_data = cpu_to_le32(wqe->send.inv_key); + if (qp->type == CMDQ_CREATE_QP_TYPE_UD || + qp->type == CMDQ_CREATE_QP_TYPE_GSI) { + sqe->q_key = cpu_to_le32(wqe->send.q_key); + sqe->length = cpu_to_le32(data_len); + ext_sqe->dst_qp = cpu_to_le32( + wqe->send.dst_qp & SQ_SEND_DST_QP_MASK); + ext_sqe->avid = cpu_to_le32(wqe->send.avid & + SQ_SEND_AVID_MASK); + sq->psn = (sq->psn + 1) & BTH_PSN_MASK; + } else { + sqe->length = cpu_to_le32(data_len); + if (qp->mtu) + pkt_num = (data_len + qp->mtu - 1) / qp->mtu; + if (!pkt_num) + pkt_num = 1; + sq->psn = (sq->psn + pkt_num) & BTH_PSN_MASK; + } + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: Send WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\twqe_size = 0x%x\n" + "\tinv_key/immdata = 0x%x\n" + "\tq_key = 0x%x\n" + "\tdst_qp = 0x%x\n" + "\tlength = 0x%x\n" + "\tavid = 0x%x\n", + sqe->wqe_type, sqe->flags, sqe->wqe_size, + sqe->inv_key_or_imm_data, sqe->q_key, ext_sqe->dst_qp, + sqe->length, ext_sqe->avid); + break; + } + case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE: + /* fall-thru */ + case BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM: + /* fall-thru */ + case BNXT_QPLIB_SWQE_TYPE_RDMA_READ: + { + struct sq_rdma_hdr *sqe = base_hdr; + struct sq_rdma_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->wqe_size = wqe_slots; + sqe->imm_data = cpu_to_le32(wqe->rdma.inv_key); + sqe->length = cpu_to_le32((u32)data_len); + ext_sqe->remote_va = cpu_to_le64(wqe->rdma.remote_va); + ext_sqe->remote_key = cpu_to_le32(wqe->rdma.r_key); + if (qp->mtu) + pkt_num = (data_len + qp->mtu - 1) / qp->mtu; + if (!pkt_num) + pkt_num = 1; + sq->psn = (sq->psn + pkt_num) & BTH_PSN_MASK; + + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: RDMA WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\twqe_size = 0x%x\n" + "\timmdata = 0x%x\n" + "\tlength = 0x%x\n" + "\tremote_va = 0x%llx\n" + "\tremote_key = 0x%x\n", + sqe->wqe_type, sqe->flags, sqe->wqe_size, + sqe->imm_data, sqe->length, ext_sqe->remote_va, + ext_sqe->remote_key); + break; + } + case BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP: + /* fall-thru */ + case BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD: + { + struct sq_atomic_hdr *sqe = base_hdr; + struct sq_atomic_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->remote_key = cpu_to_le32(wqe->atomic.r_key); + sqe->remote_va = cpu_to_le64(wqe->atomic.remote_va); + ext_sqe->swap_data = cpu_to_le64(wqe->atomic.swap_data); + ext_sqe->cmp_data = cpu_to_le64(wqe->atomic.cmp_data); + if (qp->mtu) + pkt_num = (data_len + qp->mtu - 1) / qp->mtu; + if (!pkt_num) + pkt_num = 1; + sq->psn = (sq->psn + pkt_num) & BTH_PSN_MASK; + break; + } + case BNXT_QPLIB_SWQE_TYPE_LOCAL_INV: + { + struct sq_localinvalidate_hdr *sqe = base_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->inv_l_key = cpu_to_le32(wqe->local_inv.inv_l_key); + + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: LOCAL INV WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\tinv_l_key = 0x%x\n", + sqe->wqe_type, sqe->flags, sqe->inv_l_key); + break; + } + case BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR: + { + struct sq_fr_pmr_hdr *sqe = base_hdr; + struct sq_fr_pmr_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->access_cntl = wqe->frmr.access_cntl | + SQ_FR_PMR_ACCESS_CNTL_LOCAL_WRITE; + sqe->zero_based_page_size_log = + (wqe->frmr.pg_sz_log & SQ_FR_PMR_PAGE_SIZE_LOG_MASK) << + SQ_FR_PMR_PAGE_SIZE_LOG_SFT | + (wqe->frmr.zero_based == true ? SQ_FR_PMR_ZERO_BASED : 0); + sqe->l_key = cpu_to_le32(wqe->frmr.l_key); + /* TODO: OFED only provides length of MR up to 32-bits for FRMR */ + temp32 = cpu_to_le32(wqe->frmr.length); + memcpy(sqe->length, &temp32, sizeof(wqe->frmr.length)); + sqe->numlevels_pbl_page_size_log = + ((wqe->frmr.pbl_pg_sz_log << + SQ_FR_PMR_PBL_PAGE_SIZE_LOG_SFT) & + SQ_FR_PMR_PBL_PAGE_SIZE_LOG_MASK) | + ((wqe->frmr.levels << SQ_FR_PMR_NUMLEVELS_SFT) & + SQ_FR_PMR_NUMLEVELS_MASK); + if (!wqe->frmr.levels && !wqe->frmr.pbl_ptr) { + ext_sqe->pblptr = cpu_to_le64(wqe->frmr.page_list[0]); + } else { + for (i = 0; i < wqe->frmr.page_list_len; i++) + wqe->frmr.pbl_ptr[i] = cpu_to_le64( + wqe->frmr.page_list[i] | + PTU_PTE_VALID); + ext_sqe->pblptr = cpu_to_le64(wqe->frmr.pbl_dma_ptr); + } + ext_sqe->va = cpu_to_le64(wqe->frmr.va); + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: FRMR WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\taccess_cntl = 0x%x\n" + "\tzero_based_page_size_log = 0x%x\n" + "\tl_key = 0x%x\n" + "\tlength = 0x%x\n" + "\tnumlevels_pbl_page_size_log = 0x%x\n" + "\tpblptr = 0x%llx\n" + "\tva = 0x%llx\n", + sqe->wqe_type, sqe->flags, sqe->access_cntl, + sqe->zero_based_page_size_log, sqe->l_key, + *(u32 *)sqe->length, sqe->numlevels_pbl_page_size_log, + ext_sqe->pblptr, ext_sqe->va); + break; + } + case BNXT_QPLIB_SWQE_TYPE_BIND_MW: + { + struct sq_bind_hdr *sqe = base_hdr; + struct sq_bind_ext_hdr *ext_sqe = ext_hdr; + + sqe->wqe_type = wqe->type; + sqe->flags = wqe->flags; + sqe->access_cntl = wqe->bind.access_cntl; + sqe->mw_type_zero_based = wqe->bind.mw_type | + (wqe->bind.zero_based == true ? SQ_BIND_ZERO_BASED : 0); + sqe->parent_l_key = cpu_to_le32(wqe->bind.parent_l_key); + sqe->l_key = cpu_to_le32(wqe->bind.r_key); + ext_sqe->va = cpu_to_le64(wqe->bind.va); + ext_sqe->length_lo = cpu_to_le32(wqe->bind.length); + dev_dbg(&sq_hwq->pdev->dev, + "QPLIB: FP: BIND WQE:\n" + "\twqe_type = 0x%x\n" + "\tflags = 0x%x\n" + "\taccess_cntl = 0x%x\n" + "\tmw_type_zero_based = 0x%x\n" + "\tparent_l_key = 0x%x\n" + "\tl_key = 0x%x\n" + "\tva = 0x%llx\n" + "\tlength = 0x%x\n", + sqe->wqe_type, sqe->flags, sqe->access_cntl, + sqe->mw_type_zero_based, sqe->parent_l_key, + sqe->l_key, sqe->va, ext_sqe->length_lo); + break; + } + default: + /* Bad wqe, return error */ + rc = -EINVAL; + goto done; + } + swq->next_psn = sq->psn & BTH_PSN_MASK; + bnxt_qplib_fill_psn_search(qp, wqe, swq); + +queue_err: + bnxt_qplib_swq_mod_start(sq, wqe_idx); + bnxt_qplib_hwq_incr_prod(&sq->dbinfo, sq_hwq, swq->slots); + qp->wqe_cnt++; +done: + if (sch_handler) { + nq_work = kzalloc(sizeof(*nq_work), GFP_ATOMIC); + if (nq_work) { + nq_work->cq = qp->scq; + nq_work->nq = qp->scq->nq; + INIT_WORK(&nq_work->work, bnxt_qpn_cqn_sched_task); + queue_work(qp->scq->nq->cqn_wq, &nq_work->work); + } else { + dev_err(&sq->hwq.pdev->dev, + "QPLIB: FP: Failed to allocate SQ nq_work!\n"); + rc = -ENOMEM; + } + } + return rc; +} + +void bnxt_qplib_post_recv_db(struct bnxt_qplib_qp *qp) +{ + struct bnxt_qplib_q *rq = &qp->rq; + + bnxt_qplib_ring_prod_db(&rq->dbinfo, DBC_DBC_TYPE_RQ); +} + +void bnxt_re_handle_cqn(struct bnxt_qplib_cq *cq) +{ + struct bnxt_qplib_nq *nq; + + if (!(cq && cq->nq)) + return; + + nq = cq->nq; + spin_lock_bh(&cq->compl_lock); + if (nq->cqn_handler) { + dev_dbg(&nq->res->pdev->dev, + "%s:Trigger cq = %p event nq = %p\n", + __func__, cq, nq); + nq->cqn_handler(nq, cq); + } + spin_unlock_bh(&cq->compl_lock); +} + +int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe) +{ + struct bnxt_qplib_nq_work *nq_work = NULL; + struct bnxt_qplib_q *rq = &qp->rq; + struct bnxt_qplib_hwq *rq_hwq; + struct bnxt_qplib_swq *swq; + bool sch_handler = false; + struct rq_wqe_hdr *base_hdr; + struct rq_ext_hdr *ext_hdr; + struct sq_sge *dsge; + u8 wqe_slots; + u32 wqe_idx; + u32 sw_prod; + int rc = 0; + + rq_hwq = &rq->hwq; + if (qp->state == CMDQ_MODIFY_QP_NEW_STATE_RESET) { + dev_err(&rq_hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) is in the 0x%x state\n", + qp->id, qp->state); + rc = -EINVAL; + goto done; + } + + wqe_slots = _calculate_wqe_byte(qp, wqe, NULL); + if (bnxt_qplib_queue_full(rq_hwq, rq->dbinfo.max_slot)) { + dev_err(&rq_hwq->pdev->dev, + "QPLIB: FP: QP (0x%x) RQ is full!\n", qp->id); + rc = -EINVAL; + goto done; + } + + swq = bnxt_qplib_get_swqe(rq, &wqe_idx); + swq->wr_id = wqe->wr_id; + swq->slots = rq->dbinfo.max_slot; + dev_dbg(&rq_hwq->pdev->dev, + "QPLIB: FP: post RQ wr_id[%d] = 0x%llx\n", + wqe_idx, swq->wr_id); + if (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_ERR) { + sch_handler = true; + dev_dbg(&rq_hwq->pdev->dev, "%s Error QP. Sched a flushed cmpl\n", + __func__); + goto queue_err; + } + + sw_prod = rq_hwq->prod; + base_hdr = bnxt_qplib_get_qe(rq_hwq, sw_prod, NULL); + sw_prod++; + ext_hdr = bnxt_qplib_get_qe(rq_hwq, (sw_prod % rq_hwq->depth), NULL); + sw_prod++; + memset(base_hdr, 0, sizeof(struct sq_sge)); + memset(ext_hdr, 0, sizeof(struct sq_sge)); + + if (!wqe->num_sge) { + dsge = bnxt_qplib_get_qe(rq_hwq, (sw_prod % rq_hwq->depth), NULL); + dsge->size = 0; + wqe_slots++; + } else { + bnxt_qplib_put_sges(rq_hwq, wqe->sg_list, wqe->num_sge, &sw_prod); + } + base_hdr->wqe_type = wqe->type; + base_hdr->flags = wqe->flags; + base_hdr->wqe_size = wqe_slots; + base_hdr->wr_id |= cpu_to_le32(wqe_idx); +queue_err: + bnxt_qplib_swq_mod_start(rq, wqe_idx); + bnxt_qplib_hwq_incr_prod(&rq->dbinfo, &rq->hwq, swq->slots); +done: + if (sch_handler) { + nq_work = kzalloc(sizeof(*nq_work), GFP_ATOMIC); + if (nq_work) { + nq_work->cq = qp->rcq; + nq_work->nq = qp->rcq->nq; + INIT_WORK(&nq_work->work, bnxt_qpn_cqn_sched_task); + queue_work(qp->rcq->nq->cqn_wq, &nq_work->work); + } else { + dev_err(&rq->hwq.pdev->dev, + "QPLIB: FP: Failed to allocate RQ nq_work!\n"); + rc = -ENOMEM; + } + } + return rc; +} + +/* CQ */ +int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_create_cq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_create_cq req = {}; + struct bnxt_qplib_reftbl *tbl; + unsigned long flag; + u32 pg_sz_lvl = 0; + int rc; + + hwq_attr.res = res; + hwq_attr.depth = cq->max_wqe; + hwq_attr.stride = sizeof(struct cq_base); + hwq_attr.type = HWQ_TYPE_QUEUE; + hwq_attr.sginfo = &cq->sginfo; + rc = bnxt_qplib_alloc_init_hwq(&cq->hwq, &hwq_attr); + if (rc) + goto exit; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_CREATE_CQ, + sizeof(req)); + + if (!cq->dpi) { + dev_err(&rcfw->pdev->dev, + "QPLIB: FP: CREATE_CQ failed due to NULL DPI\n"); + return -EINVAL; + } + req.dpi = cpu_to_le32(cq->dpi->dpi); + req.cq_handle = cpu_to_le64(cq->cq_handle); + + req.cq_size = cpu_to_le32(cq->max_wqe); + req.pbl = cpu_to_le64(_get_base_addr(&cq->hwq)); + pg_sz_lvl = _get_base_pg_size(&cq->hwq) << CMDQ_CREATE_CQ_PG_SIZE_SFT; + pg_sz_lvl |= ((cq->hwq.level & CMDQ_CREATE_CQ_LVL_MASK) << + CMDQ_CREATE_CQ_LVL_SFT); + req.pg_size_lvl = cpu_to_le32(pg_sz_lvl); + + req.cq_fco_cnq_id = cpu_to_le32( + (cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) << + CMDQ_CREATE_CQ_CNQ_ID_SFT); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail; + cq->id = le32_to_cpu(resp.xid); + cq->period = BNXT_QPLIB_QUEUE_START_PERIOD; + init_waitqueue_head(&cq->waitq); + INIT_LIST_HEAD(&cq->sqf_head); + INIT_LIST_HEAD(&cq->rqf_head); + spin_lock_init(&cq->flush_lock); + spin_lock_init(&cq->compl_lock); + + /* init dbinfo */ + cq->cctx = res->cctx; + cq->dbinfo.hwq = &cq->hwq; + cq->dbinfo.xid = cq->id; + cq->dbinfo.db = cq->dpi->dbr; + cq->dbinfo.priv_db = res->dpi_tbl.priv_db; + cq->dbinfo.flags = 0; + cq->dbinfo.toggle = 0; + cq->dbinfo.res = res; + cq->dbinfo.seed = cq->id; + spin_lock_init(&cq->dbinfo.lock); + cq->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + cq->dbinfo.shadow_key_arm_ena = BNXT_QPLIB_DBR_KEY_INVALID; + + tbl = &res->reftbl.cqref; + spin_lock_irqsave(&tbl->lock, flag); + tbl->rec[GET_TBL_INDEX(cq->id, tbl)].xid = cq->id; + tbl->rec[GET_TBL_INDEX(cq->id, tbl)].handle = cq; + spin_unlock_irqrestore(&tbl->lock, flag); + + bnxt_qplib_armen_db(&cq->dbinfo, DBC_DBC_TYPE_CQ_ARMENA); + return 0; + +fail: + bnxt_qplib_free_hwq(res, &cq->hwq); +exit: + return rc; +} + +int bnxt_qplib_modify_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) +{ + /* TODO: Modify CQ threshold are passed to the HW via DBR */ + return 0; +} + +void bnxt_qplib_resize_cq_complete(struct bnxt_qplib_res *res, + struct bnxt_qplib_cq *cq) +{ + bnxt_qplib_free_hwq(res, &cq->hwq); + memcpy(&cq->hwq, &cq->resize_hwq, sizeof(cq->hwq)); + /* Reset only the cons bit in the flags */ + cq->dbinfo.flags &= ~(1UL << BNXT_QPLIB_FLAG_EPOCH_CONS_SHIFT); + + /* Tell HW to switch over to the new CQ */ + if (!cq->resize_hwq.is_user) + bnxt_qplib_cq_coffack_db(&cq->dbinfo); +} + +int bnxt_qplib_resize_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq, + int new_cqes) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_resize_cq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_resize_cq req = {}; + u32 pgsz = 0, lvl = 0, nsz = 0; + struct bnxt_qplib_pbl *pbl; + u16 count = -1; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_RESIZE_CQ, + sizeof(req)); + + hwq_attr.sginfo = &cq->sginfo; + hwq_attr.res = res; + hwq_attr.depth = new_cqes; + hwq_attr.stride = sizeof(struct cq_base); + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&cq->resize_hwq, &hwq_attr); + if (rc) + return rc; + + dev_dbg(&rcfw->pdev->dev, "QPLIB: FP: %s: pbl_lvl: %d\n", __func__, + cq->resize_hwq.level); + req.cq_cid = cpu_to_le32(cq->id); + pbl = &cq->resize_hwq.pbl[PBL_LVL_0]; + pgsz = ((pbl->pg_size == ROCE_PG_SIZE_4K ? CMDQ_RESIZE_CQ_PG_SIZE_PG_4K : + pbl->pg_size == ROCE_PG_SIZE_8K ? CMDQ_RESIZE_CQ_PG_SIZE_PG_8K : + pbl->pg_size == ROCE_PG_SIZE_64K ? CMDQ_RESIZE_CQ_PG_SIZE_PG_64K : + pbl->pg_size == ROCE_PG_SIZE_2M ? CMDQ_RESIZE_CQ_PG_SIZE_PG_2M : + pbl->pg_size == ROCE_PG_SIZE_8M ? CMDQ_RESIZE_CQ_PG_SIZE_PG_8M : + pbl->pg_size == ROCE_PG_SIZE_1G ? CMDQ_RESIZE_CQ_PG_SIZE_PG_1G : + CMDQ_RESIZE_CQ_PG_SIZE_PG_4K) & CMDQ_RESIZE_CQ_PG_SIZE_MASK); + lvl = (cq->resize_hwq.level << CMDQ_RESIZE_CQ_LVL_SFT) & + CMDQ_RESIZE_CQ_LVL_MASK; + nsz = (new_cqes << CMDQ_RESIZE_CQ_NEW_CQ_SIZE_SFT) & + CMDQ_RESIZE_CQ_NEW_CQ_SIZE_MASK; + req.new_cq_size_pg_size_lvl = cpu_to_le32(nsz|pgsz|lvl); + req.new_pbl = cpu_to_le64(pbl->pg_map_arr[0]); + + if (!cq->resize_hwq.is_user) + set_bit(CQ_FLAGS_RESIZE_IN_PROG, &cq->flags); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail; + + if (!cq->resize_hwq.is_user) { +wait: + /* Wait here for the HW to switch the CQ over */ + if (wait_event_interruptible_timeout(cq->waitq, + !test_bit(CQ_FLAGS_RESIZE_IN_PROG, &cq->flags), + msecs_to_jiffies(CQ_RESIZE_WAIT_TIME_MS)) == + -ERESTARTSYS && count--) + goto wait; + + if (test_bit(CQ_FLAGS_RESIZE_IN_PROG, &cq->flags)) { + dev_err(&rcfw->pdev->dev, + "QPLIB: FP: RESIZE_CQ timed out\n"); + rc = -ETIMEDOUT; + goto fail; + } + + bnxt_qplib_resize_cq_complete(res, cq); + } + + return 0; +fail: + if (!cq->resize_hwq.is_user) { + bnxt_qplib_free_hwq(res, &cq->resize_hwq); + clear_bit(CQ_FLAGS_RESIZE_IN_PROG, &cq->flags); + } + return rc; +} + +void bnxt_qplib_free_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) +{ + bnxt_qplib_free_hwq(res, &cq->hwq); +} + +static void bnxt_qplib_sync_cq(struct bnxt_qplib_cq *cq) +{ + struct bnxt_qplib_nq *nq = cq->nq; + /* Flush any pending work and synchronize irq */ + flush_workqueue(cq->nq->cqn_wq); + mutex_lock(&nq->lock); + if (nq->requested) + synchronize_irq(nq->msix_vec); + mutex_unlock(&nq->lock); +} + +int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_destroy_cq_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_cq req = {}; + struct bnxt_qplib_reftbl *tbl; + u16 total_cnq_events; + unsigned long flag; + int rc; + + tbl = &res->reftbl.cqref; + spin_lock_irqsave(&tbl->lock, flag); + tbl->rec[GET_TBL_INDEX(cq->id, tbl)].handle = NULL; + tbl->rec[GET_TBL_INDEX(cq->id, tbl)].xid = 0; + spin_unlock_irqrestore(&tbl->lock, flag); + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DESTROY_CQ, + sizeof(req)); + + req.cq_cid = cpu_to_le32(cq->id); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + + total_cnq_events = le16_to_cpu(resp.total_cnq_events); + if (total_cnq_events >= 0) + dev_dbg(&rcfw->pdev->dev, + "%s: cq_id = 0x%x cq = 0x%p resp.total_cnq_events = 0x%x\n", + __func__, cq->id, cq, total_cnq_events); + __wait_for_all_nqes(cq, total_cnq_events); + bnxt_qplib_sync_cq(cq); + bnxt_qplib_free_hwq(res, &cq->hwq); + return 0; +} + +static int __flush_sq(struct bnxt_qplib_q *sq, struct bnxt_qplib_qp *qp, + struct bnxt_qplib_cqe **pcqe, int *budget) +{ + struct bnxt_qplib_cqe *cqe; + u32 start, last; + int rc = 0; + + /* Now complete all outstanding SQEs with FLUSHED_ERR */ + start = sq->swq_start; + cqe = *pcqe; + while (*budget) { + last = sq->swq_last; + if (start == last) { + break; + } + /* Skip the FENCE WQE completions */ + if (sq->swq[last].wr_id == BNXT_QPLIB_FENCE_WRID) { + bnxt_re_legacy_cancel_phantom_processing(qp); + goto skip_compl; + } + + memset(cqe, 0, sizeof(*cqe)); + cqe->status = CQ_REQ_STATUS_WORK_REQUEST_FLUSHED_ERR; + cqe->opcode = CQ_BASE_CQE_TYPE_REQ; + cqe->qp_handle = (u64)qp; + cqe->wr_id = sq->swq[last].wr_id; + cqe->src_qp = qp->id; + cqe->type = sq->swq[last].type; + dev_dbg(&sq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed terminal Req \n"); + dev_dbg(&sq->hwq.pdev->dev, + "QPLIB: wr_id[%d] = 0x%llx with status 0x%x\n", + last, cqe->wr_id, cqe->status); + cqe++; + (*budget)--; +skip_compl: + bnxt_qplib_hwq_incr_cons(sq->hwq.depth, + &sq->hwq.cons, + sq->swq[last].slots, + &sq->dbinfo.flags); + sq->swq_last = sq->swq[last].next_idx; + } + *pcqe = cqe; + if (!*budget && sq->swq_last != start) + /* Out of budget */ + rc = -EAGAIN; + dev_dbg(&sq->hwq.pdev->dev, "QPLIB: FP: Flush SQ rc = 0x%x\n", rc); + + return rc; +} + +static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp, + struct bnxt_qplib_cqe **pcqe, int *budget) +{ + struct bnxt_qplib_cqe *cqe; + u32 start, last; + int opcode = 0; + int rc = 0; + + switch (qp->type) { + case CMDQ_CREATE_QP1_TYPE_GSI: + opcode = CQ_BASE_CQE_TYPE_RES_RAWETH_QP1; + break; + case CMDQ_CREATE_QP_TYPE_RC: + opcode = CQ_BASE_CQE_TYPE_RES_RC; + break; + case CMDQ_CREATE_QP_TYPE_UD: + opcode = CQ_BASE_CQE_TYPE_RES_UD; + break; + } + + /* Flush the rest of the RQ */ + start = rq->swq_start; + cqe = *pcqe; + while (*budget) { + last = rq->swq_last; + if (last == start) + break; + memset(cqe, 0, sizeof(*cqe)); + cqe->status = + CQ_RES_RC_STATUS_WORK_REQUEST_FLUSHED_ERR; + cqe->opcode = opcode; + cqe->qp_handle = (u64)qp; + cqe->wr_id = rq->swq[last].wr_id; + dev_dbg(&rq->hwq.pdev->dev, "QPLIB: FP: CQ Processed Res RC \n"); + dev_dbg(&rq->hwq.pdev->dev, + "QPLIB: rq[%d] = 0x%llx with status 0x%x\n", + last, cqe->wr_id, cqe->status); + cqe++; + (*budget)--; + bnxt_qplib_hwq_incr_cons(rq->hwq.depth, + &rq->hwq.cons, + rq->swq[last].slots, + &rq->dbinfo.flags); + rq->swq_last = rq->swq[last].next_idx; + } + *pcqe = cqe; + if (!*budget && rq->swq_last != start) + /* Out of budget */ + rc = -EAGAIN; + + dev_dbg(&rq->hwq.pdev->dev, "QPLIB: FP: Flush RQ rc = 0x%x\n", rc); + return rc; +} + +void bnxt_qplib_mark_qp_error(void *qp_handle) +{ + struct bnxt_qplib_qp *qp = qp_handle; + + if (!qp) + return; + + /* Must block new posting of SQ and RQ */ + qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_ERR; + qp->state = qp->cur_qp_state; + + /* Add qp to flush list of the CQ */ + if (!qp->is_user) + bnxt_qplib_add_flush_qp(qp); +} + +/* Note: SQE is valid from sw_sq_cons up to cqe_sq_cons (exclusive) + * CQE is track from sw_cq_cons to max_element but valid only if VALID=1 + */ +static int bnxt_re_legacy_do_wa9060(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_cq *cq, + u32 cq_cons, u32 swq_last, + u32 cqe_sq_cons) +{ + struct bnxt_qplib_q *sq = &qp->sq; + struct bnxt_qplib_swq *swq; + u32 peek_sw_cq_cons, peek_sq_cons_idx, peek_flags; + struct cq_terminal *peek_term_hwcqe; + struct cq_req *peek_req_hwcqe; + struct bnxt_qplib_qp *peek_qp; + struct bnxt_qplib_q *peek_sq; + struct cq_base *peek_hwcqe; + int i, rc = 0; + + /* Check for the psn_search marking before completing */ + swq = &sq->swq[swq_last]; + if (swq->psn_search && + le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) { + /* Unmark */ + swq->psn_search->flags_next_psn = cpu_to_le32 + (le32_to_cpu(swq->psn_search->flags_next_psn) + & ~0x80000000); + dev_dbg(&cq->hwq.pdev->dev, + "FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n", + cq_cons, qp->id, swq_last, cqe_sq_cons); + sq->condition = true; + sq->legacy_send_phantom = true; + + /* TODO: Only ARM if the previous SQE is ARMALL */ + bnxt_qplib_ring_db(&cq->dbinfo, DBC_DBC_TYPE_CQ_ARMALL); + + rc = -EAGAIN; + goto out; + } + if (sq->condition == true) { + /* Peek at the completions */ + peek_flags = cq->dbinfo.flags; + peek_sw_cq_cons = cq_cons; + i = cq->hwq.depth; + while (i--) { + peek_hwcqe = bnxt_qplib_get_qe(&cq->hwq, + peek_sw_cq_cons, NULL); + /* If the next hwcqe is VALID */ + if (CQE_CMP_VALID(peek_hwcqe, peek_flags)) { + /* If the next hwcqe is a REQ */ + dma_rmb(); + switch (peek_hwcqe->cqe_type_toggle & + CQ_BASE_CQE_TYPE_MASK) { + case CQ_BASE_CQE_TYPE_REQ: + peek_req_hwcqe = (struct cq_req *) + peek_hwcqe; + peek_qp = (struct bnxt_qplib_qp *) + le64_to_cpu( + peek_req_hwcqe->qp_handle); + peek_sq = &peek_qp->sq; + peek_sq_cons_idx = + ((le16_to_cpu( + peek_req_hwcqe->sq_cons_idx) + - 1) % sq->max_wqe); + /* If the hwcqe's sq's wr_id matches */ + if (peek_sq == sq && + sq->swq[peek_sq_cons_idx].wr_id == + BNXT_QPLIB_FENCE_WRID) { + /* Unbreak only if the phantom + comes back */ + dev_dbg(&cq->hwq.pdev->dev, + "FP: Process Req qp=0x%x current sq cons sw=0x%x cqe=0x%x\n", + qp->id, swq_last, + cqe_sq_cons); + sq->condition = false; + sq->single = true; + sq->phantom_cqe_cnt++; + dev_dbg(&cq->hwq.pdev->dev, + "qp %#x condition restored at peek cq_cons=%#x sq_cons_idx %#x, phantom_cqe_cnt: %d unmark\n", + peek_qp->id, + peek_sw_cq_cons, + peek_sq_cons_idx, + sq->phantom_cqe_cnt); + rc = 0; + goto out; + } + break; + + case CQ_BASE_CQE_TYPE_TERMINAL: + /* In case the QP has gone into the + error state */ + peek_term_hwcqe = (struct cq_terminal *) + peek_hwcqe; + peek_qp = (struct bnxt_qplib_qp *) + le64_to_cpu( + peek_term_hwcqe->qp_handle); + if (peek_qp == qp) { + sq->condition = false; + rc = 0; + goto out; + } + break; + default: + break; + } + /* Valid but not the phantom, so keep looping */ + } else { + /* Not valid yet, just exit and wait */ + rc = -EINVAL; + goto out; + } + bnxt_qplib_hwq_incr_cons(cq->hwq.depth, + &peek_sw_cq_cons, + 1, &peek_flags); + } + dev_err(&cq->hwq.pdev->dev, + "Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x\n", + cq_cons, qp->id, swq_last, cqe_sq_cons); + rc = -EINVAL; + } +out: + return rc; +} + +static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, + struct cq_req *hwcqe, + struct bnxt_qplib_cqe **pcqe, int *budget, + u32 cq_cons, struct bnxt_qplib_qp **lib_qp) +{ + struct bnxt_qplib_qp *qp; + struct bnxt_qplib_q *sq; + struct bnxt_qplib_cqe *cqe; + u32 cqe_sq_cons; + struct bnxt_qplib_swq *swq; + int rc = 0; + + qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); + dev_dbg(&cq->hwq.pdev->dev, "FP: Process Req qp=0x%p\n", qp); + if (!qp) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: Process Req qp is NULL\n"); + return -EINVAL; + } + sq = &qp->sq; + + cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe; + if (qp->sq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + goto done; + } + + /* Require to walk the sq's swq to fabricate CQEs for all previously + * signaled SWQEs due to CQE aggregation from the current sq cons + * to the cqe_sq_cons + */ + cqe = *pcqe; + while (*budget) { + if (sq->swq_last == cqe_sq_cons) + /* Done */ + break; + + swq = &sq->swq[sq->swq_last]; + memset(cqe, 0, sizeof(*cqe)); + cqe->opcode = CQ_BASE_CQE_TYPE_REQ; + cqe->qp_handle = (u64)qp; + cqe->src_qp = qp->id; + cqe->wr_id = swq->wr_id; + + if (cqe->wr_id == BNXT_QPLIB_FENCE_WRID) + goto skip; + + cqe->type = swq->type; + + /* For the last CQE, check for status. For errors, regardless + * of the request being signaled or not, it must complete with + * the hwcqe error status + */ + if (swq->next_idx == cqe_sq_cons && + hwcqe->status != CQ_REQ_STATUS_OK) { + cqe->status = hwcqe->status; + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed Req \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: QP 0x%x wr_id[%d] = 0x%lx vendor type 0x%x with vendor status 0x%x\n", + cqe->src_qp, sq->swq_last, cqe->wr_id, cqe->type, cqe->status); + cqe++; + (*budget)--; + bnxt_qplib_mark_qp_error(qp); + } else { + /* Before we complete, do WA 9060 */ + if (!_is_chip_gen_p5_p7(qp->cctx)) { + if (bnxt_re_legacy_do_wa9060(qp, cq, cq_cons, + sq->swq_last, + cqe_sq_cons)) { + *lib_qp = qp; + goto out; + } + } + if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) { + + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed Req \n"); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: wr_id[%d] = 0x%llx \n", + sq->swq_last, cqe->wr_id); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: with status 0x%x\n", cqe->status); + cqe->status = CQ_REQ_STATUS_OK; + cqe++; + (*budget)--; + } + } +skip: + bnxt_qplib_hwq_incr_cons(sq->hwq.depth, &sq->hwq.cons, + swq->slots, &sq->dbinfo.flags); + sq->swq_last = swq->next_idx; + if (sq->single == true) + break; + } +out: + *pcqe = cqe; + if (sq->swq_last != cqe_sq_cons) { + /* Out of budget */ + rc = -EAGAIN; + goto done; + } + /* Back to normal completion mode only after it has completed all of + the WC for this CQE */ + sq->single = false; +done: + return rc; +} + +static void bnxt_qplib_release_srqe(struct bnxt_qplib_srq *srq, u32 tag) +{ + spin_lock(&srq->hwq.lock); + srq->swq[srq->last_idx].next_idx = (int)tag; + srq->last_idx = (int)tag; + srq->swq[srq->last_idx].next_idx = -1; + bnxt_qplib_hwq_incr_cons(srq->hwq.depth, &srq->hwq.cons, + srq->dbinfo.max_slot, &srq->dbinfo.flags); + spin_unlock(&srq->hwq.lock); +} + +static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq, + struct cq_res_rc *hwcqe, + struct bnxt_qplib_cqe **pcqe, + int *budget) +{ + struct bnxt_qplib_srq *srq; + struct bnxt_qplib_cqe *cqe; + struct bnxt_qplib_qp *qp; + struct bnxt_qplib_q *rq; + u32 wr_id_idx; + int rc = 0; + + qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); + if (!qp) { + dev_err(&cq->hwq.pdev->dev, "QPLIB: process_cq RC qp is NULL\n"); + return -EINVAL; + } + if (qp->rq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + goto done; + } + + cqe = *pcqe; + cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK; + cqe->length = le32_to_cpu(hwcqe->length); + cqe->invrkey = le32_to_cpu(hwcqe->imm_data_or_inv_r_key); + cqe->mr_handle = le64_to_cpu(hwcqe->mr_handle); + cqe->flags = le16_to_cpu(hwcqe->flags); + cqe->status = hwcqe->status; + cqe->qp_handle = (u64)(unsigned long)qp; + + wr_id_idx = le32_to_cpu(hwcqe->srq_or_rq_wr_id) & + CQ_RES_RC_SRQ_OR_RQ_WR_ID_MASK; + if (cqe->flags & CQ_RES_RC_FLAGS_SRQ_SRQ) { + srq = qp->srq; + if (!srq) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: SRQ used but not defined??\n"); + return -EINVAL; + } + if (wr_id_idx > srq->hwq.depth - 1) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process RC \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: wr_id idx 0x%x exceeded SRQ max 0x%x\n", + wr_id_idx, srq->hwq.depth); + return -EINVAL; + } + cqe->wr_id = srq->swq[wr_id_idx].wr_id; + bnxt_qplib_release_srqe(srq, wr_id_idx); + dev_dbg(&srq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed RC SRQ wr_id[%d] = 0x%llx\n", + wr_id_idx, cqe->wr_id); + cqe++; + (*budget)--; + *pcqe = cqe; + } else { + rq = &qp->rq; + if (wr_id_idx > (rq->max_wqe - 1)) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process RC \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: wr_id idx 0x%x exceeded RQ max 0x%x\n", + wr_id_idx, rq->hwq.depth); + return -EINVAL; + } + if (wr_id_idx != rq->swq_last) + return -EINVAL; + cqe->wr_id = rq->swq[rq->swq_last].wr_id; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed RC RQ wr_id[%d] = 0x%llx\n", + rq->swq_last, cqe->wr_id); + cqe++; + (*budget)--; + bnxt_qplib_hwq_incr_cons(rq->hwq.depth, &rq->hwq.cons, + rq->swq[rq->swq_last].slots, + &rq->dbinfo.flags); + rq->swq_last = rq->swq[rq->swq_last].next_idx; + *pcqe = cqe; + + if (hwcqe->status != CQ_RES_RC_STATUS_OK) + bnxt_qplib_mark_qp_error(qp); + } +done: + return rc; +} + +static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, + struct cq_res_ud_v2 *hwcqe, + struct bnxt_qplib_cqe **pcqe, + int *budget) +{ + struct bnxt_qplib_srq *srq; + struct bnxt_qplib_cqe *cqe; + struct bnxt_qplib_qp *qp; + struct bnxt_qplib_q *rq; + u32 wr_id_idx; + int rc = 0; + u16 *smac; + + qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); + if (!qp) { + dev_err(&cq->hwq.pdev->dev, "QPLIB: process_cq UD qp is NULL\n"); + return -EINVAL; + } + if (qp->rq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + goto done; + } + cqe = *pcqe; + cqe->opcode = hwcqe->cqe_type_toggle & CQ_RES_UD_V2_CQE_TYPE_MASK; + cqe->length = le32_to_cpu((hwcqe->length & CQ_RES_UD_V2_LENGTH_MASK)); + cqe->cfa_meta = le16_to_cpu(hwcqe->cfa_metadata0); + /* V2 format has metadata1 */ + cqe->cfa_meta |= (((le32_to_cpu(hwcqe->src_qp_high_srq_or_rq_wr_id) & + CQ_RES_UD_V2_CFA_METADATA1_MASK) >> + CQ_RES_UD_V2_CFA_METADATA1_SFT) << + BNXT_QPLIB_META1_SHIFT); + cqe->invrkey = le32_to_cpu(hwcqe->imm_data); + cqe->flags = le16_to_cpu(hwcqe->flags); + cqe->status = hwcqe->status; + cqe->qp_handle = (u64)(unsigned long)qp; + smac = (u16 *)cqe->smac; + smac[2] = ntohs(le16_to_cpu(hwcqe->src_mac[0])); + smac[1] = ntohs(le16_to_cpu(hwcqe->src_mac[1])); + smac[0] = ntohs(le16_to_cpu(hwcqe->src_mac[2])); + wr_id_idx = le32_to_cpu(hwcqe->src_qp_high_srq_or_rq_wr_id) + & CQ_RES_UD_V2_SRQ_OR_RQ_WR_ID_MASK; + cqe->src_qp = le16_to_cpu(hwcqe->src_qp_low) | + ((le32_to_cpu( + hwcqe->src_qp_high_srq_or_rq_wr_id) & + CQ_RES_UD_V2_SRC_QP_HIGH_MASK) >> 8); + + if (cqe->flags & CQ_RES_UD_V2_FLAGS_SRQ) { + srq = qp->srq; + if (!srq) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: SRQ used but not defined??\n"); + return -EINVAL; + } + if (wr_id_idx > srq->hwq.depth - 1) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process UD \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: wr_id idx 0x%x exceeded SRQ max 0x%x\n", + wr_id_idx, srq->hwq.depth); + return -EINVAL; + } + cqe->wr_id = srq->swq[wr_id_idx].wr_id; + bnxt_qplib_release_srqe(srq, wr_id_idx); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed UD SRQ wr_id[%d] = 0x%llx\n", + wr_id_idx, cqe->wr_id); + cqe++; + (*budget)--; + *pcqe = cqe; + } else { + rq = &qp->rq; + if (wr_id_idx > (rq->max_wqe - 1)) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process UD \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: wr_id idx 0x%x exceeded RQ max 0x%x\n", + wr_id_idx, rq->hwq.depth); + return -EINVAL; + } + if (rq->swq_last != wr_id_idx) + return -EINVAL; + + cqe->wr_id = rq->swq[rq->swq_last].wr_id; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed UD RQ wr_id[%d] = 0x%llx\n", + rq->swq_last, cqe->wr_id); + cqe++; + (*budget)--; + bnxt_qplib_hwq_incr_cons(rq->hwq.depth, &rq->hwq.cons, + rq->swq[rq->swq_last].slots, + &rq->dbinfo.flags); + rq->swq_last = rq->swq[rq->swq_last].next_idx; + *pcqe = cqe; + + if (hwcqe->status != CQ_RES_UD_V2_STATUS_OK) + bnxt_qplib_mark_qp_error(qp); + } +done: + return rc; +} + +bool bnxt_qplib_is_cq_empty(struct bnxt_qplib_cq *cq) +{ + + struct cq_base *hw_cqe; + unsigned long flags; + bool rc = true; + + spin_lock_irqsave(&cq->hwq.lock, flags); + hw_cqe = bnxt_qplib_get_qe(&cq->hwq, cq->hwq.cons, NULL); + + /* Check for Valid bit. If the CQE is valid, return false */ + rc = !CQE_CMP_VALID(hw_cqe, cq->dbinfo.flags); + spin_unlock_irqrestore(&cq->hwq.lock, flags); + return rc; +} + +static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq, + struct cq_res_raweth_qp1 *hwcqe, + struct bnxt_qplib_cqe **pcqe, + int *budget) +{ + struct bnxt_qplib_qp *qp; + struct bnxt_qplib_q *rq; + struct bnxt_qplib_srq *srq; + struct bnxt_qplib_cqe *cqe; + u32 wr_id_idx; + int rc = 0; + + qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); + if (!qp) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: process_cq Raw/QP1 qp is NULL\n"); + return -EINVAL; + } + if (qp->rq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + goto done; + } + cqe = *pcqe; + cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK; + cqe->flags = le16_to_cpu(hwcqe->flags); + cqe->qp_handle = (u64)(unsigned long)qp; + + wr_id_idx = le32_to_cpu(hwcqe->raweth_qp1_payload_offset_srq_or_rq_wr_id) + & CQ_RES_RAWETH_QP1_SRQ_OR_RQ_WR_ID_MASK; + cqe->src_qp = qp->id; + if (qp->id == 1 && !cqe->length) { + /* Add workaround for the length misdetection */ + cqe->length = 296; + } else { + cqe->length = le16_to_cpu(hwcqe->length); + } + cqe->pkey_index = qp->pkey_index; + memcpy(cqe->smac, qp->smac, 6); + + cqe->raweth_qp1_flags = le16_to_cpu(hwcqe->raweth_qp1_flags); + cqe->raweth_qp1_flags2 = le32_to_cpu(hwcqe->raweth_qp1_flags2); + cqe->raweth_qp1_metadata = le32_to_cpu(hwcqe->raweth_qp1_metadata); + + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: raweth_qp1_flags = 0x%x raweth_qp1_flags2 = 0x%x\n", + cqe->raweth_qp1_flags, cqe->raweth_qp1_flags2); + + if (cqe->flags & CQ_RES_RAWETH_QP1_FLAGS_SRQ_SRQ) { + srq = qp->srq; + if (!srq) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: SRQ used but not defined??\n"); + return -EINVAL; + } + if (wr_id_idx > srq->hwq.depth - 1) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process Raw/QP1 \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: wr_id idx 0x%x exceeded SRQ max 0x%x\n", + wr_id_idx, srq->hwq.depth); + return -EINVAL; + } + cqe->wr_id = srq->swq[wr_id_idx].wr_id; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed Raw/QP1 SRQ \n"); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: wr_id[%d] = 0x%llx with status = 0x%x\n", + wr_id_idx, cqe->wr_id, hwcqe->status); + cqe++; + (*budget)--; + srq->hwq.cons++; + *pcqe = cqe; + } else { + rq = &qp->rq; + if (wr_id_idx > (rq->max_wqe - 1)) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process Raw/QP1 RQ wr_id \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: ix 0x%x exceeded RQ max 0x%x\n", + wr_id_idx, rq->max_wqe); + return -EINVAL; + } + if (wr_id_idx != rq->swq_last) + return -EINVAL; + cqe->wr_id = rq->swq[rq->swq_last].wr_id; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed Raw/QP1 RQ \n"); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: wr_id[%d] = 0x%llx with status = 0x%x\n", + wr_id_idx, cqe->wr_id, hwcqe->status); + cqe++; + (*budget)--; + bnxt_qplib_hwq_incr_cons(rq->hwq.depth, &rq->hwq.cons, + rq->swq[wr_id_idx].slots, + &rq->dbinfo.flags); + rq->swq_last = rq->swq[rq->swq_last].next_idx; + *pcqe = cqe; + + if (hwcqe->status != CQ_RES_RC_STATUS_OK) + bnxt_qplib_mark_qp_error(qp); + } +done: + return rc; +} + +static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, + struct cq_terminal *hwcqe, + struct bnxt_qplib_cqe **pcqe, + int *budget) +{ + struct bnxt_qplib_q *sq, *rq; + struct bnxt_qplib_cqe *cqe; + struct bnxt_qplib_qp *qp; + u32 swq_last; + u32 cqe_cons; + int rc = 0; + + /* Check the Status */ + if (hwcqe->status != CQ_TERMINAL_STATUS_OK) + dev_warn(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process Terminal Error status = 0x%x\n", + hwcqe->status); + + qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); + if (!qp) + return -EINVAL; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process terminal for qp (0x%x)\n", qp->id); + + /* Terminal CQE requires all posted RQEs to complete with FLUSHED_ERR + * from the current rq->cons to the rq->prod regardless what the + * rq->cons the terminal CQE indicates. + */ + bnxt_qplib_mark_qp_error(qp); + + sq = &qp->sq; + rq = &qp->rq; + + cqe_cons = le16_to_cpu(hwcqe->sq_cons_idx); + if (cqe_cons == 0xFFFF) + goto do_rq; + + cqe_cons %= sq->max_wqe; + if (qp->sq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + goto sq_done; + } + + /* Terminal CQE can also include aggregated successful CQEs prior. + So we must complete all CQEs from the current sq's cons to the + cq_cons with status OK */ + cqe = *pcqe; + while (*budget) { + /*sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);*/ + swq_last = sq->swq_last; + if (swq_last == cqe_cons) + break; + if (sq->swq[swq_last].flags & SQ_SEND_FLAGS_SIGNAL_COMP) { + memset(cqe, 0, sizeof(*cqe)); + cqe->status = CQ_REQ_STATUS_OK; + cqe->opcode = CQ_BASE_CQE_TYPE_REQ; + cqe->qp_handle = (u64)qp; + cqe->src_qp = qp->id; + cqe->wr_id = sq->swq[swq_last].wr_id; + cqe->type = sq->swq[swq_last].type; + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed terminal Req \n"); + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: wr_id[%d] = 0x%llx with status 0x%x\n", + swq_last, cqe->wr_id, cqe->status); + cqe++; + (*budget)--; + } + bnxt_qplib_hwq_incr_cons(sq->hwq.depth, &sq->hwq.cons, + sq->swq[swq_last].slots, + &sq->dbinfo.flags); + sq->swq_last = sq->swq[swq_last].next_idx; + } + *pcqe = cqe; + if (!*budget && swq_last != cqe_cons) { + /* Out of budget */ + rc = -EAGAIN; + goto sq_done; + } +sq_done: + if (rc) + return rc; +do_rq: + cqe_cons = le16_to_cpu(hwcqe->rq_cons_idx); + if (cqe_cons == 0xFFFF) { + goto done; + } else if (cqe_cons > (rq->max_wqe - 1)) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Processed terminal \n"); + dev_err(&cq->hwq.pdev->dev, + "QPLIB: reported rq_cons_idx 0x%x exceeds max 0x%x\n", + cqe_cons, rq->hwq.depth); + goto done; + } + if (qp->rq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); + rc = 0; + goto rq_done; + } + +rq_done: +done: + return rc; +} + +static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq, + struct cq_cutoff *hwcqe) +{ + /* Check the Status */ + if (hwcqe->status != CQ_CUTOFF_STATUS_OK) { + dev_err(&cq->hwq.pdev->dev, + "QPLIB: FP: CQ Process Cutoff Error status = 0x%x\n", + hwcqe->status); + return -EINVAL; + } + clear_bit(CQ_FLAGS_RESIZE_IN_PROG, &cq->flags); + wake_up_interruptible(&cq->waitq); + + dev_dbg(&cq->hwq.pdev->dev, "QPLIB: FP: CQ Processed Cutoff\n"); + return 0; +} + +int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq, + struct bnxt_qplib_cqe *cqe, + int num_cqes) +{ + struct bnxt_qplib_qp *qp = NULL; + u32 budget = num_cqes; + unsigned long flags; + + spin_lock_irqsave(&cq->flush_lock, flags); + list_for_each_entry(qp, &cq->sqf_head, sq_flush) { + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: Flushing SQ QP= %p\n", + qp); + __flush_sq(&qp->sq, qp, &cqe, &budget); + } + + list_for_each_entry(qp, &cq->rqf_head, rq_flush) { + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: FP: Flushing RQ QP= %p\n", + qp); + __flush_rq(&qp->rq, qp, &cqe, &budget); + } + spin_unlock_irqrestore(&cq->flush_lock, flags); + + return num_cqes - budget; +} + +int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, + int num_cqes, struct bnxt_qplib_qp **lib_qp) +{ + struct cq_base *hw_cqe; + u32 hw_polled = 0; + int budget, rc = 0; + u8 type; + + budget = num_cqes; + + while (budget) { + hw_cqe = bnxt_qplib_get_qe(&cq->hwq, cq->hwq.cons, NULL); + + /* Check for Valid bit */ + if (!CQE_CMP_VALID(hw_cqe, cq->dbinfo.flags)) + break; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + /* From the device's respective CQE format to qplib_wc*/ + type = hw_cqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK; + switch (type) { + case CQ_BASE_CQE_TYPE_REQ: + rc = bnxt_qplib_cq_process_req(cq, + (struct cq_req *)hw_cqe, &cqe, &budget, + cq->hwq.cons, lib_qp); + break; + case CQ_BASE_CQE_TYPE_RES_RC: + rc = bnxt_qplib_cq_process_res_rc(cq, + (struct cq_res_rc *)hw_cqe, &cqe, + &budget); + break; + case CQ_BASE_CQE_TYPE_RES_UD: + rc = bnxt_qplib_cq_process_res_ud(cq, + (struct cq_res_ud_v2 *)hw_cqe, + &cqe, &budget); + break; + case CQ_BASE_CQE_TYPE_RES_RAWETH_QP1: + rc = bnxt_qplib_cq_process_res_raweth_qp1(cq, + (struct cq_res_raweth_qp1 *) + hw_cqe, &cqe, &budget); + break; + case CQ_BASE_CQE_TYPE_TERMINAL: + rc = bnxt_qplib_cq_process_terminal(cq, + (struct cq_terminal *)hw_cqe, + &cqe, &budget); + break; + case CQ_BASE_CQE_TYPE_CUT_OFF: + bnxt_qplib_cq_process_cutoff(cq, + (struct cq_cutoff *)hw_cqe); + /* Done processing this CQ */ + goto exit; + default: + dev_err(&cq->hwq.pdev->dev, + "QPLIB: process_cq unknown type 0x%x\n", + hw_cqe->cqe_type_toggle & + CQ_BASE_CQE_TYPE_MASK); + rc = -EINVAL; + break; + } + if (rc < 0) { + dev_dbg(&cq->hwq.pdev->dev, + "QPLIB: process_cqe rc = 0x%x\n", rc); + if (rc == -EAGAIN) + break; + /* Error while processing the CQE, just skip to the + next one */ + if (type != CQ_BASE_CQE_TYPE_TERMINAL) + dev_err(&cq->hwq.pdev->dev, + "QPLIB: process_cqe error rc = 0x%x\n", + rc); + } + hw_polled++; + bnxt_qplib_hwq_incr_cons(cq->hwq.depth, &cq->hwq.cons, + 1, &cq->dbinfo.flags); + } + if (hw_polled) + bnxt_qplib_ring_db(&cq->dbinfo, DBC_DBC_TYPE_CQ); +exit: + return num_cqes - budget; +} + +void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type) +{ + cq->dbinfo.toggle = cq->toggle; + if (arm_type) + bnxt_qplib_ring_db(&cq->dbinfo, arm_type); + /* Using cq->arm_state variable to track whether to issue cq handler */ + atomic_set(&cq->arm_state, 1); +} + +void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp) +{ + flush_workqueue(qp->scq->nq->cqn_wq); + if (qp->scq != qp->rcq) + flush_workqueue(qp->rcq->nq->cqn_wq); +} diff --git a/sys/dev/bnxt/bnxt_re/qplib_fp.h b/sys/dev/bnxt/bnxt_re/qplib_fp.h new file mode 100644 index 000000000000..527c377f0aa5 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_fp.h @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Fast Path Operators (header) + */ + +#ifndef __BNXT_QPLIB_FP_H__ +#define __BNXT_QPLIB_FP_H__ + +/* Temp header structures for SQ */ +struct sq_ud_ext_hdr { + __le32 dst_qp; + __le32 avid; + __le64 rsvd; +}; + +struct sq_raw_ext_hdr { + __le32 cfa_meta; + __le32 rsvd0; + __le64 rsvd1; +}; + +struct sq_rdma_ext_hdr { + __le64 remote_va; + __le32 remote_key; + __le32 rsvd; +}; + +struct sq_atomic_ext_hdr { + __le64 swap_data; + __le64 cmp_data; +}; + +struct sq_fr_pmr_ext_hdr { + __le64 pblptr; + __le64 va; +}; + +struct sq_bind_ext_hdr { + __le64 va; + __le32 length_lo; + __le32 length_hi; +}; + +struct rq_ext_hdr { + __le64 rsvd1; + __le64 rsvd2; +}; + +#define BNXT_QPLIB_ETHTYPE_ROCEV1 0x8915 + +struct bnxt_qplib_srq { + struct bnxt_qplib_pd *pd; + struct bnxt_qplib_dpi *dpi; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_qplib_cq *cq; + struct bnxt_qplib_swq *swq; + struct bnxt_qplib_hwq hwq; + struct bnxt_qplib_db_info dbinfo; + struct bnxt_qplib_sg_info sginfo; + u64 srq_handle; + u32 id; + u16 wqe_size; + u32 max_wqe; + u32 max_sge; + u32 threshold; + bool arm_req; + int start_idx; + int last_idx; + u16 eventq_hw_ring_id; + bool is_user; + spinlock_t lock; +}; + +struct bnxt_qplib_sge { + u64 addr; + u32 size; + u32 lkey; +}; + +/* + * Buffer space for ETH(14), IP or GRH(40), UDP header(8) + * and ib_bth + ib_deth (20). + * Max required is 82 when RoCE V2 is enabled + */ + +/* + * RoCE V1 (38 bytes needed) + * +------------+----------+--------+--------+-------+ + * |Eth-hdr(14B)| GRH (40B)|bth+deth| Mad | iCRC | + * | | supplied | 20B |payload | 4B | + * | | by user |supplied| 256B | | + * | | mad | |by user | | + * | | | | | | + * | sge 1 | sge 2 | sge 3 | sge 4 | sge 5 | + * +------------+----------+--------+--------+-------+ + */ + +/* + * RoCE V2-IPv4 (46 Bytes needed) + * +------------+----------+--------+--------+-------+ + * |Eth-hdr(14B)| IP-hdr |UDP-hdr | Mad | iCRC | + * | | supplied | 8B |payload | 4B | + * | | by user |bth+deth| 256B | | + * | | mad lower| 20B |supplied| | + * | | 20B out | (sge 3)|by user | | + * | | of 40B | | | | + * | | grh space| | | | + * | sge 1 | sge 2 | sge 3 | sge 4 | sge 5 | + * +------------+----------+--------+--------+-------+ + */ + +/* + * RoCE V2-IPv6 (46 Bytes needed) + * +------------+----------+--------+--------+-------+ + * |Eth-hdr(14B)| IPv6 |UDP-hdr | Mad | iCRC | + * | | supplied | 8B |payload | 4B | + * | | by user |bth+deth| 256B | | + * | | mad lower| 20B |supplied| | + * | | 40 bytes | |by user | | + * | | grh space| | | | + * | | | | | | + * | sge 1 | sge 2 | sge 3 | sge 4 | sge 5 | + * +------------+----------+--------+--------+-------+ + */ + +#define BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE 74 +#define BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2 86 +#define BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE 46 +#define BNXT_QPLIB_MAX_QP1_RQ_ETH_HDR_SIZE 14 +#define BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2 512 +#define BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV4 20 +#define BNXT_QPLIB_MAX_GRH_HDR_SIZE_IPV6 40 +#define BNXT_QPLIB_MAX_QP1_RQ_BDETH_HDR_SIZE 20 +#define BNXT_QPLIB_MAX_SQSZ 0xFFFF + +struct bnxt_qplib_hdrbuf { + dma_addr_t dma_map; + void *va; + u32 len; + u32 step; +}; + +struct bnxt_qplib_swq { + u64 wr_id; + int next_idx; + u8 type; + u8 flags; + u32 start_psn; + u32 next_psn; + u32 slot_idx; + u8 slots; + /* WIP: make it void * to handle legacy also */ + struct sq_psn_search *psn_search; + void *inline_data; +}; + +struct bnxt_qplib_swqe { + /* General */ +#define BNXT_QPLIB_FENCE_WRID 0x46454E43 /* "FENC" */ +#define BNXT_QPLIB_QP1_DUMMY_WRID 0x44554D59 /* "DUMY" */ + u64 wr_id; + u8 reqs_type; + u8 type; +#define BNXT_QPLIB_SWQE_TYPE_SEND 0 +#define BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM 1 +#define BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV 2 +#define BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE 4 +#define BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM 5 +#define BNXT_QPLIB_SWQE_TYPE_RDMA_READ 6 +#define BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP 8 +#define BNXT_QPLIB_SWQE_TYPE_ATOMIC_FETCH_AND_ADD 11 +#define BNXT_QPLIB_SWQE_TYPE_LOCAL_INV 12 +#define BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR 13 +#define BNXT_QPLIB_SWQE_TYPE_REG_MR 13 +#define BNXT_QPLIB_SWQE_TYPE_BIND_MW 14 +#define BNXT_QPLIB_SWQE_TYPE_RECV 128 +#define BNXT_QPLIB_SWQE_TYPE_RECV_RDMA_IMM 129 + u8 flags; +#define BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP (1 << 0) +#define BNXT_QPLIB_SWQE_FLAGS_RD_ATOMIC_FENCE (1 << 1) +#define BNXT_QPLIB_SWQE_FLAGS_UC_FENCE (1 << 2) +#define BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT (1 << 3) +#define BNXT_QPLIB_SWQE_FLAGS_INLINE (1 << 4) + struct bnxt_qplib_sge *sg_list; + int num_sge; + + union { + /* Send, with imm, inval key */ + struct { + union { + __be32 imm_data; + u32 inv_key; + }; + u32 q_key; + u32 dst_qp; + u16 avid; + } send; + + /* Send Raw Ethernet and QP1 */ + struct { + u16 lflags; + u16 cfa_action; + u32 cfa_meta; + } rawqp1; + + /* RDMA write, with imm, read */ + struct { + union { + __be32 imm_data; + u32 inv_key; + }; + u64 remote_va; + u32 r_key; + } rdma; + + /* Atomic cmp/swap, fetch/add */ + struct { + u64 remote_va; + u32 r_key; + u64 swap_data; + u64 cmp_data; + } atomic; + + /* Local Invalidate */ + struct { + u32 inv_l_key; + } local_inv; + + /* FR-PMR */ + struct { + u8 access_cntl; + u8 pg_sz_log; + bool zero_based; + u32 l_key; + u32 length; + u8 pbl_pg_sz_log; +#define BNXT_QPLIB_SWQE_PAGE_SIZE_4K 0 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_8K 1 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_64K 4 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_256K 6 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_1M 8 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_2M 9 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_4M 10 +#define BNXT_QPLIB_SWQE_PAGE_SIZE_1G 18 + u8 levels; +#define PAGE_SHIFT_4K 12 + __le64 *pbl_ptr; + dma_addr_t pbl_dma_ptr; + u64 *page_list; + u16 page_list_len; + u64 va; + } frmr; + + /* Bind */ + struct { + u8 access_cntl; +#define BNXT_QPLIB_BIND_SWQE_ACCESS_LOCAL_WRITE (1 << 0) +#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_READ (1 << 1) +#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_WRITE (1 << 2) +#define BNXT_QPLIB_BIND_SWQE_ACCESS_REMOTE_ATOMIC (1 << 3) +#define BNXT_QPLIB_BIND_SWQE_ACCESS_WINDOW_BIND (1 << 4) + bool zero_based; + u8 mw_type; + u32 parent_l_key; + u32 r_key; + u64 va; + u32 length; + } bind; + }; +}; + +struct bnxt_qplib_q { + struct bnxt_qplib_swq *swq; + struct bnxt_qplib_db_info dbinfo; + struct bnxt_qplib_sg_info sginfo; + struct bnxt_qplib_hwq hwq; + u32 max_wqe; + u16 max_sge; + u16 wqe_size; + u16 q_full_delta; + u32 psn; + bool condition; + bool single; + bool legacy_send_phantom; + u32 phantom_wqe_cnt; + u32 phantom_cqe_cnt; + u32 next_cq_cons; + bool flushed; + u32 swq_start; + u32 swq_last; +}; + +#define BNXT_QPLIB_PPP_REQ 0x1 +#define BNXT_QPLIB_PPP_ST_IDX_SHIFT 0x1 + +struct bnxt_qplib_ppp { + u32 dpi; + u8 req; + u8 st_idx_en; +}; + +struct bnxt_qplib_qp { + struct bnxt_qplib_pd *pd; + struct bnxt_qplib_dpi *dpi; + struct bnxt_qplib_chip_ctx *cctx; + u64 qp_handle; +#define BNXT_QPLIB_QP_ID_INVALID 0xFFFFFFFF + u32 id; + u8 type; + u8 sig_type; + u8 wqe_mode; + u8 state; + u8 cur_qp_state; + u8 is_user; + u64 modify_flags; + u32 max_inline_data; + u32 mtu; + u32 path_mtu; + bool en_sqd_async_notify; + u16 pkey_index; + u32 qkey; + u32 dest_qp_id; + u8 access; + u8 timeout; + u8 retry_cnt; + u8 rnr_retry; + u64 wqe_cnt; + u32 min_rnr_timer; + u32 max_rd_atomic; + u32 max_dest_rd_atomic; + u32 dest_qpn; + u8 smac[6]; + u16 vlan_id; + u8 nw_type; + u16 port_id; + struct bnxt_qplib_ah ah; + struct bnxt_qplib_ppp ppp; + +#define BTH_PSN_MASK ((1 << 24) - 1) + /* SQ */ + struct bnxt_qplib_q sq; + /* RQ */ + struct bnxt_qplib_q rq; + /* SRQ */ + struct bnxt_qplib_srq *srq; + /* CQ */ + struct bnxt_qplib_cq *scq; + struct bnxt_qplib_cq *rcq; + /* IRRQ and ORRQ */ + struct bnxt_qplib_hwq irrq; + struct bnxt_qplib_hwq orrq; + /* Header buffer for QP1 */ + struct bnxt_qplib_hdrbuf *sq_hdr_buf; + struct bnxt_qplib_hdrbuf *rq_hdr_buf; + + /* ToS */ + u8 tos_ecn; + u8 tos_dscp; + /* To track the SQ and RQ flush list */ + struct list_head sq_flush; + struct list_head rq_flush; + /* 4 bytes of QP's scrabled mac received from FW */ + u32 lag_src_mac; + u32 msn; + u32 msn_tbl_sz; + /* get devflags in PI code */ + u16 dev_cap_flags; +}; + + +#define CQE_CMP_VALID(hdr, pass) \ + (!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \ + !(pass & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK)) + +static inline u32 __bnxt_qplib_get_avail(struct bnxt_qplib_hwq *hwq) +{ + int cons, prod, avail; + + /* False full is possible retrying post-send makes sense */ + cons = hwq->cons; + prod = hwq->prod; + avail = cons - prod; + if (cons <= prod) + avail += hwq->depth; + return avail; +} + +static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_hwq *hwq, u8 slots) +{ + return __bnxt_qplib_get_avail(hwq) <= slots; +} + +struct bnxt_qplib_cqe { + u8 status; + u8 type; + u8 opcode; + u32 length; + /* Lower 16 is cfa_metadata0, Upper 16 is cfa_metadata1 */ + u32 cfa_meta; +#define BNXT_QPLIB_META1_SHIFT 16 +#define BNXT_QPLIB_CQE_CFA_META1_VALID 0x80000UL + u64 wr_id; + union { + __be32 immdata; + u32 invrkey; + }; + u64 qp_handle; + u64 mr_handle; + u16 flags; + u8 smac[6]; + u32 src_qp; + u16 raweth_qp1_flags; + u16 raweth_qp1_errors; + u16 raweth_qp1_cfa_code; + u32 raweth_qp1_flags2; + u32 raweth_qp1_metadata; + u8 raweth_qp1_payload_offset; + u16 pkey_index; +}; + +#define BNXT_QPLIB_QUEUE_START_PERIOD 0x01 +struct bnxt_qplib_cq { + struct bnxt_qplib_dpi *dpi; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_qplib_nq *nq; + struct bnxt_qplib_db_info dbinfo; + struct bnxt_qplib_sg_info sginfo; + struct bnxt_qplib_hwq hwq; + struct bnxt_qplib_hwq resize_hwq; + struct list_head sqf_head; + struct list_head rqf_head; + u32 max_wqe; + u32 id; + u16 count; + u16 period; + u32 cnq_hw_ring_id; + u64 cq_handle; + atomic_t arm_state; +#define CQ_RESIZE_WAIT_TIME_MS 500 + unsigned long flags; +#define CQ_FLAGS_RESIZE_IN_PROG 1 + wait_queue_head_t waitq; + spinlock_t flush_lock; /* lock flush queue list */ + spinlock_t compl_lock; /* synch CQ handlers */ + u16 cnq_events; + bool is_cq_err_event; + bool destroyed; + u8 toggle; +}; + +#define BNXT_QPLIB_MAX_IRRQE_ENTRY_SIZE sizeof(struct xrrq_irrq) +#define BNXT_QPLIB_MAX_ORRQE_ENTRY_SIZE sizeof(struct xrrq_orrq) +#define IRD_LIMIT_TO_IRRQ_SLOTS(x) (2 * x + 2) +#define IRRQ_SLOTS_TO_IRD_LIMIT(s) ((s >> 1) - 1) +#define ORD_LIMIT_TO_ORRQ_SLOTS(x) (x + 1) +#define ORRQ_SLOTS_TO_ORD_LIMIT(s) (s - 1) + +#define NQE_CMP_VALID(hdr, pass) \ + (!!(le32_to_cpu((hdr)->info63_v & 0xffffffff) & NQ_BASE_V) == \ + !(pass & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK)) + +#define BNXT_QPLIB_NQE_MAX_CNT (128 * 1024) + +/* MSN table print macros for debugging */ +#define BNXT_RE_MSN_IDX(m) (((m) & SQ_MSN_SEARCH_START_IDX_MASK) >> \ + SQ_MSN_SEARCH_START_IDX_SFT) +#define BNXT_RE_MSN_NPSN(m) (((m) & SQ_MSN_SEARCH_NEXT_PSN_MASK) >> \ + SQ_MSN_SEARCH_NEXT_PSN_SFT) +#define BNXT_RE_MSN_SPSN(m) (((m) & SQ_MSN_SEARCH_START_PSN_MASK) >> \ + SQ_MSN_SEARCH_START_PSN_SFT) +#define BNXT_MSN_TBLE_SGE 6 + +struct bnxt_qplib_nq_stats { + u64 num_dbqne_processed; + u64 num_srqne_processed; + u64 num_cqne_processed; + u64 num_tasklet_resched; + u64 num_nq_rearm; +}; + +struct bnxt_qplib_nq_db { + struct bnxt_qplib_reg_desc reg; + void __iomem *db; + struct bnxt_qplib_db_info dbinfo; +}; + +typedef int (*cqn_handler_t)(struct bnxt_qplib_nq *nq, + struct bnxt_qplib_cq *cq); +typedef int (*srqn_handler_t)(struct bnxt_qplib_nq *nq, + struct bnxt_qplib_srq *srq, u8 event); + +struct bnxt_qplib_nq { + struct bnxt_qplib_res *res; + struct bnxt_qplib_hwq hwq; + struct bnxt_qplib_nq_db nq_db; + + char *name; + u16 ring_id; + int msix_vec; + bool requested; + int budget; + u32 load; + struct mutex lock; + + cqn_handler_t cqn_handler; + srqn_handler_t srqn_handler; + struct workqueue_struct *cqn_wq; + struct bnxt_qplib_nq_stats stats; +}; + +struct bnxt_qplib_nq_work { + struct work_struct work; + struct bnxt_qplib_nq *nq; + struct bnxt_qplib_cq *cq; +}; + +static inline dma_addr_t +bnxt_qplib_get_qp_buf_from_index(struct bnxt_qplib_qp *qp, u32 index) +{ + struct bnxt_qplib_hdrbuf *buf; + + buf = qp->rq_hdr_buf; + return (buf->dma_map + index * buf->step); +} + +void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill); +void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq); +int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, + int msix_vector, bool need_init); +int bnxt_qplib_enable_nq(struct bnxt_qplib_nq *nq, int nq_idx, + int msix_vector, int bar_reg_offset, + cqn_handler_t cqn_handler, + srqn_handler_t srq_handler); +int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq); +int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq); +int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq); +int bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res, + struct bnxt_qplib_srq *srq); +int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, + struct bnxt_qplib_swqe *wqe); +int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp); +void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); +void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_sge *sge); +void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_sge *sge); +u32 bnxt_qplib_get_rq_prod_index(struct bnxt_qplib_qp *qp); +void bnxt_qplib_post_send_db(struct bnxt_qplib_qp *qp); +int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe); +void bnxt_qplib_post_recv_db(struct bnxt_qplib_qp *qp); +int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, + struct bnxt_qplib_swqe *wqe); +int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); +int bnxt_qplib_modify_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); +int bnxt_qplib_resize_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq, + int new_cqes); +void bnxt_qplib_resize_cq_complete(struct bnxt_qplib_res *res, + struct bnxt_qplib_cq *cq); +int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); +void bnxt_qplib_free_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); +int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, + int num, struct bnxt_qplib_qp **qp); +bool bnxt_qplib_is_cq_empty(struct bnxt_qplib_cq *cq); +void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type); +void bnxt_qplib_free_nq_mem(struct bnxt_qplib_nq *nq); +int bnxt_qplib_alloc_nq_mem(struct bnxt_qplib_res *res, + struct bnxt_qplib_nq *nq); +void bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp); +void bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp); +int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq, + struct bnxt_qplib_cqe *cqe, + int num_cqes); +void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp); +void bnxt_qplib_free_hdr_buf(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp); +int bnxt_qplib_alloc_hdr_buf(struct bnxt_qplib_res *res, + struct bnxt_qplib_qp *qp, u32 slen, u32 rlen); + +static inline bool __can_request_ppp(struct bnxt_qplib_qp *qp) +{ + bool can_request = false; + + if (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_RESET && + qp->state == CMDQ_MODIFY_QP_NEW_STATE_INIT && + qp->ppp.req && + !(qp->ppp.st_idx_en & + CREQ_MODIFY_QP_RESP_PINGPONG_PUSH_ENABLED)) + can_request = true; + return can_request; +} + +/* MSN table update inlin */ +static inline uint64_t bnxt_re_update_msn_tbl(uint32_t st_idx, uint32_t npsn, uint32_t start_psn) +{ + return cpu_to_le64((((u64)(st_idx) << SQ_MSN_SEARCH_START_IDX_SFT) & + SQ_MSN_SEARCH_START_IDX_MASK) | + (((u64)(npsn) << SQ_MSN_SEARCH_NEXT_PSN_SFT) & + SQ_MSN_SEARCH_NEXT_PSN_MASK) | + (((start_psn) << SQ_MSN_SEARCH_START_PSN_SFT) & + SQ_MSN_SEARCH_START_PSN_MASK)); +} + +void bnxt_re_schedule_dbq_event(struct bnxt_qplib_res *res); +#endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_rcfw.c b/sys/dev/bnxt/bnxt_re/qplib_rcfw.c new file mode 100644 index 000000000000..7e3453a1e044 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_rcfw.c @@ -0,0 +1,1338 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: RDMA Controller HW interface + */ + +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/dma-mapping.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/hardirq.h> +#include <linux/device.h> + +#include "hsi_struct_def.h" +#include "qplib_tlv.h" +#include "qplib_res.h" +#include "qplib_sp.h" +#include "qplib_rcfw.h" +#include "bnxt_re.h" + +static void bnxt_qplib_service_creq(unsigned long data); + +int __check_cmdq_stall(struct bnxt_qplib_rcfw *rcfw, + u32 *cur_prod, u32 *cur_cons) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + + cmdq = &rcfw->cmdq; + + if (*cur_prod == cmdq->hwq.prod && + *cur_cons == cmdq->hwq.cons) + /* No activity on CMDQ or CREQ. FW down */ + return -ETIMEDOUT; + + *cur_prod = cmdq->hwq.prod; + *cur_cons = cmdq->hwq.cons; + return 0; +} + +static int bnxt_qplib_map_rc(u8 opcode) +{ + switch (opcode) { + case CMDQ_BASE_OPCODE_DESTROY_QP: + case CMDQ_BASE_OPCODE_DESTROY_SRQ: + case CMDQ_BASE_OPCODE_DESTROY_CQ: + case CMDQ_BASE_OPCODE_DEALLOCATE_KEY: + case CMDQ_BASE_OPCODE_DEREGISTER_MR: + case CMDQ_BASE_OPCODE_DELETE_GID: + case CMDQ_BASE_OPCODE_DESTROY_QP1: + case CMDQ_BASE_OPCODE_DESTROY_AH: + case CMDQ_BASE_OPCODE_DEINITIALIZE_FW: + case CMDQ_BASE_OPCODE_MODIFY_ROCE_CC: + case CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE: + return 0; + default: + return -ETIMEDOUT; + } +} + +/** + * bnxt_re_is_fw_stalled - Check firmware health + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * If firmware has not responded any rcfw command within + * rcfw->max_timeout, consider firmware as stalled. + * + * Returns: + * 0 if firmware is responding + * -ENODEV if firmware is not responding + */ +static int bnxt_re_is_fw_stalled(struct bnxt_qplib_rcfw *rcfw, u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_crsqe *crsqe; + + crsqe = &rcfw->crsqe_tbl[cookie]; + cmdq = &rcfw->cmdq; + + if (time_after(jiffies, cmdq->last_seen + + (rcfw->max_timeout * HZ))) { + dev_warn_ratelimited(&rcfw->pdev->dev, + "%s: FW STALL Detected. cmdq[%#x]=%#x waited (%ld > %d) msec active %d\n", + __func__, cookie, crsqe->opcode, + (long)jiffies_to_msecs(jiffies - cmdq->last_seen), + rcfw->max_timeout * 1000, + crsqe->is_in_used); + return -ENODEV; + } + + return 0; +} +/** + * __wait_for_resp - Don't hold the cpu context and wait for response + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * Wait for command completion in sleepable context. + * + * Returns: + * 0 if command is completed by firmware. + * Non zero error code for rest of the case. + */ +static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_crsqe *crsqe; + unsigned long issue_time; + int ret; + + cmdq = &rcfw->cmdq; + issue_time = jiffies; + crsqe = &rcfw->crsqe_tbl[cookie]; + + do { + if (RCFW_NO_FW_ACCESS(rcfw)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + /* Non zero means command completed */ + ret = wait_event_timeout(cmdq->waitq, + !crsqe->is_in_used || + RCFW_NO_FW_ACCESS(rcfw), + msecs_to_jiffies(rcfw->max_timeout * 1000)); + + if (!crsqe->is_in_used) + return 0; + /* + * Take care if interrupt miss or other cases like DBR drop + */ + bnxt_qplib_service_creq((unsigned long)rcfw); + dev_warn_ratelimited(&rcfw->pdev->dev, + "Non-Blocking QPLIB: cmdq[%#x]=%#x waited (%lu) msec bit %d\n", + cookie, crsqe->opcode, + (long)jiffies_to_msecs(jiffies - issue_time), + crsqe->is_in_used); + + if (!crsqe->is_in_used) + return 0; + + ret = bnxt_re_is_fw_stalled(rcfw, cookie); + if (ret) + return ret; + + } while (true); +}; + +/** + * __block_for_resp - hold the cpu context and wait for response + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * This function will hold the cpu (non-sleepable context) and + * wait for command completion. Maximum holding interval is 8 second. + * + * Returns: + * -ETIMEOUT if command is not completed in specific time interval. + * 0 if command is completed by firmware. + */ +static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; + struct bnxt_qplib_crsqe *crsqe; + unsigned long issue_time = 0; + + issue_time = jiffies; + crsqe = &rcfw->crsqe_tbl[cookie]; + + do { + if (RCFW_NO_FW_ACCESS(rcfw)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + udelay(1); + + /* Below call is must since there can be a deadlock + * if interrupt is mapped to the same cpu + */ + bnxt_qplib_service_creq((unsigned long)rcfw); + if (!crsqe->is_in_used) + return 0; + + } while (time_before(jiffies, issue_time + (8 * HZ))); + + dev_warn_ratelimited(&rcfw->pdev->dev, + "Blocking QPLIB: cmdq[%#x]=%#x taken (%lu) msec", + cookie, crsqe->opcode, + (long)jiffies_to_msecs(jiffies - issue_time)); + + return -ETIMEDOUT; +}; + +/* __send_message_no_waiter - get cookie and post the message. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * This function will just post and don't bother about completion. + * Current design of this function is - + * user must hold the completion queue hwq->lock. + * user must have used existing completion and free the resources. + * this function will not check queue full condition. + * this function will explicitly set is_waiter_alive=false. + * current use case is - send destroy_ah if create_ah is return + * after waiter of create_ah is lost. It can be extended for other + * use case as well. + * + * Returns: Nothing + * + */ +static void __send_message_no_waiter(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) +{ + struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; + struct bnxt_qplib_hwq *cmdq_hwq = &cmdq->hwq; + struct bnxt_qplib_crsqe *crsqe; + struct bnxt_qplib_cmdqe *cmdqe; + u32 sw_prod, cmdq_prod, bsize; + u16 cookie; + u8 *preq; + + cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE; + __set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie)); + crsqe = &rcfw->crsqe_tbl[cookie]; + + /* Set cmd_size in terms of 16B slots in req. */ + bsize = bnxt_qplib_set_cmd_slots(msg->req); + /* GET_CMD_SIZE would return number of slots in either case of tlv + * and non-tlv commands after call to bnxt_qplib_set_cmd_slots() + */ + crsqe->send_timestamp = jiffies; + crsqe->is_internal_cmd = true; + crsqe->is_waiter_alive = false; + crsqe->is_in_used = true; + crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz); + + preq = (u8 *)msg->req; + do { + /* Locate the next cmdq slot */ + sw_prod = HWQ_CMP(cmdq_hwq->prod, cmdq_hwq); + cmdqe = bnxt_qplib_get_qe(cmdq_hwq, sw_prod, NULL); + /* Copy a segment of the req cmd to the cmdq */ + memset(cmdqe, 0, sizeof(*cmdqe)); + memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe))); + preq += min_t(u32, bsize, sizeof(*cmdqe)); + bsize -= min_t(u32, bsize, sizeof(*cmdqe)); + cmdq_hwq->prod++; + } while (bsize > 0); + cmdq->seq_num++; + + cmdq_prod = cmdq_hwq->prod & 0xFFFF; + atomic_inc(&rcfw->timeout_send); + /* ring CMDQ DB */ + wmb(); + writel(cmdq_prod, cmdq->cmdq_mbox.prod); + writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db); +} + +static int __send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) +{ + u32 bsize, free_slots, required_slots; + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_crsqe *crsqe; + struct bnxt_qplib_cmdqe *cmdqe; + struct bnxt_qplib_hwq *cmdq_hwq; + u32 sw_prod, cmdq_prod; + struct pci_dev *pdev; + unsigned long flags; + u16 cookie; + u8 opcode; + u8 *preq; + + cmdq = &rcfw->cmdq; + cmdq_hwq = &cmdq->hwq; + pdev = rcfw->pdev; + opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz); + + /* Cmdq are in 16-byte units, each request can consume 1 or more + cmdqe */ + spin_lock_irqsave(&cmdq_hwq->lock, flags); + required_slots = bnxt_qplib_get_cmd_slots(msg->req); + free_slots = HWQ_FREE_SLOTS(cmdq_hwq); + cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE; + crsqe = &rcfw->crsqe_tbl[cookie]; + + if (required_slots >= free_slots) { + dev_warn_ratelimited(&pdev->dev, + "QPLIB: RCFW: CMDQ is full req/free %d/%d!\n", + required_slots, free_slots); + rcfw->cmdq_full_dbg++; + spin_unlock_irqrestore(&cmdq_hwq->lock, flags); + return -EAGAIN; + } + + if (crsqe->is_in_used) + panic("QPLIB: Cookie was not requested %d\n", + cookie); + + if (msg->block) + cookie |= RCFW_CMD_IS_BLOCKING; + __set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie)); + + /* Set cmd_size in terms of 16B slots in req. */ + bsize = bnxt_qplib_set_cmd_slots(msg->req); + /* GET_CMD_SIZE would return number of slots in either case of tlv + * and non-tlv commands after call to bnxt_qplib_set_cmd_slots() + */ + crsqe->send_timestamp = jiffies; + crsqe->free_slots = free_slots; + crsqe->resp = (struct creq_qp_event *)msg->resp; + crsqe->resp->cookie = cpu_to_le16(cookie); + crsqe->is_internal_cmd = false; + crsqe->is_waiter_alive = true; + crsqe->is_in_used = true; + crsqe->opcode = opcode; + crsqe->requested_qp_state = msg->qp_state; + + crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz); + if (__get_cmdq_base_resp_size(msg->req, msg->req_sz) && msg->sb) { + struct bnxt_qplib_rcfw_sbuf *sbuf = msg->sb; + + __set_cmdq_base_resp_addr(msg->req, msg->req_sz, + cpu_to_le64(sbuf->dma_addr)); + __set_cmdq_base_resp_size(msg->req, msg->req_sz, + ALIGN(sbuf->size, BNXT_QPLIB_CMDQE_UNITS) / + BNXT_QPLIB_CMDQE_UNITS); + } + + preq = (u8 *)msg->req; + do { + /* Locate the next cmdq slot */ + sw_prod = HWQ_CMP(cmdq_hwq->prod, cmdq_hwq); + cmdqe = bnxt_qplib_get_qe(cmdq_hwq, sw_prod, NULL); + /* Copy a segment of the req cmd to the cmdq */ + memset(cmdqe, 0, sizeof(*cmdqe)); + memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe))); + preq += min_t(u32, bsize, sizeof(*cmdqe)); + bsize -= min_t(u32, bsize, sizeof(*cmdqe)); + cmdq_hwq->prod++; + } while (bsize > 0); + cmdq->seq_num++; + + cmdq_prod = cmdq_hwq->prod & 0xFFFF; + if (test_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags)) { + /* The very first doorbell write + * is required to set this flag + * which prompts the FW to reset + * its internal pointers + */ + cmdq_prod |= BIT(FIRMWARE_FIRST_FLAG); + clear_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags); + } + /* ring CMDQ DB */ + wmb(); + writel(cmdq_prod, cmdq->cmdq_mbox.prod); + writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db); + + dev_dbg(&pdev->dev, "QPLIB: RCFW sent request with 0x%x 0x%x 0x%x\n", + cmdq_prod, cmdq_hwq->prod, crsqe->req_size); + dev_dbg(&pdev->dev, + "QPLIB: opcode 0x%x with cookie 0x%x at cmdq/crsq 0x%p/0x%p\n", + opcode, + __get_cmdq_base_cookie(msg->req, msg->req_sz), + cmdqe, crsqe); + spin_unlock_irqrestore(&cmdq_hwq->lock, flags); + /* Return the CREQ response pointer */ + return 0; +} + +/** + * __poll_for_resp - self poll completion for rcfw command + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * It works same as __wait_for_resp except this function will + * do self polling in sort interval since interrupt is disabled. + * This function can not be called from non-sleepable context. + * + * Returns: + * -ETIMEOUT if command is not completed in specific time interval. + * 0 if command is completed by firmware. + */ +static int __poll_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; + struct bnxt_qplib_crsqe *crsqe; + unsigned long issue_time; + int ret; + + issue_time = jiffies; + crsqe = &rcfw->crsqe_tbl[cookie]; + + do { + if (RCFW_NO_FW_ACCESS(rcfw)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + usleep_range(1000, 1001); + + bnxt_qplib_service_creq((unsigned long)rcfw); + if (!crsqe->is_in_used) + return 0; + + if (jiffies_to_msecs(jiffies - issue_time) > + (rcfw->max_timeout * 1000)) { + dev_warn_ratelimited(&rcfw->pdev->dev, + "Self Polling QPLIB: cmdq[%#x]=%#x taken (%lu) msec", + cookie, crsqe->opcode, + (long)jiffies_to_msecs(jiffies - issue_time)); + ret = bnxt_re_is_fw_stalled(rcfw, cookie); + if (ret) + return ret; + } + } while (true); + +}; + +static int __send_message_basic_sanity(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg, u8 opcode) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + + cmdq = &rcfw->cmdq; + + /* Prevent posting if f/w is not in a state to process */ + if (RCFW_NO_FW_ACCESS(rcfw)) + return -ENXIO; + + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + if (test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && + opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) { + dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!\n"); + return -EINVAL; + } + + if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && + (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC && + opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW && + opcode != CMDQ_BASE_OPCODE_QUERY_VERSION)) { + dev_err(&rcfw->pdev->dev, + "QPLIB: RCFW not initialized, reject opcode 0x%x\n", + opcode); + return -ENOTSUPP; + } + + return 0; +} + +/* This function will just post and do not bother about completion */ +static void __destroy_timedout_ah(struct bnxt_qplib_rcfw *rcfw, + struct creq_create_ah_resp *create_ah_resp) +{ + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_ah req = {}; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DESTROY_AH, + sizeof(req)); + req.ah_cid = create_ah_resp->xid; + msg.req = (struct cmdq_base *)&req; + msg.req_sz = sizeof(req); + __send_message_no_waiter(rcfw, &msg); + dev_warn_ratelimited(&rcfw->pdev->dev, + "From %s: ah_cid = %d timeout_send %d\n", __func__, + req.ah_cid, + atomic_read(&rcfw->timeout_send)); +} + +/** + * __bnxt_qplib_rcfw_send_message - qplib interface to send + * and complete rcfw command. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * This function does not account shadow queue depth. It will send + * all the command unconditionally as long as send queue is not full. + * + * Returns: + * 0 if command completed by firmware. + * Non zero if the command is not completed by firmware. + */ +static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) +{ + struct bnxt_qplib_crsqe *crsqe; + struct creq_qp_event *event; + unsigned long flags; + u16 cookie; + int rc = 0; + u8 opcode; + + opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz); + + rc = __send_message_basic_sanity(rcfw, msg, opcode); + if (rc) + return rc == -ENXIO ? bnxt_qplib_map_rc(opcode) : rc; + + rc = __send_message(rcfw, msg); + if (rc) + return rc; + + cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, + msg->req_sz)) & RCFW_MAX_COOKIE_VALUE; + + + if (msg->block) + rc = __block_for_resp(rcfw, cookie); + else if (atomic_read(&rcfw->rcfw_intr_enabled)) + rc = __wait_for_resp(rcfw, cookie); + else + rc = __poll_for_resp(rcfw, cookie); + + if (rc) { + /* First check if it is FW stall. + * Use hwq.lock to avoid race with actual completion. + */ + spin_lock_irqsave(&rcfw->cmdq.hwq.lock, flags); + crsqe = &rcfw->crsqe_tbl[cookie]; + crsqe->is_waiter_alive = false; + if (rc == -ENODEV) + set_bit(FIRMWARE_STALL_DETECTED, &rcfw->cmdq.flags); + spin_unlock_irqrestore(&rcfw->cmdq.hwq.lock, flags); + + return -ETIMEDOUT; + } + + event = (struct creq_qp_event *)msg->resp; + if (event->status) { + /* failed with status */ + dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x (%s) status %d\n", + cookie, opcode, GET_OPCODE_TYPE(opcode), event->status); + rc = -EFAULT; + /* + * Workaround to avoid errors in the stack during bond + * creation and deletion. + * Disable error returned for ADD_GID/DEL_GID + */ + if (opcode == CMDQ_BASE_OPCODE_ADD_GID || + opcode == CMDQ_BASE_OPCODE_DELETE_GID) + rc = 0; + } + + dev_dbg(&pdev->dev, "QPLIB: %s:%d - op 0x%x (%s), cookie 0x%x -- Return: e->status 0x%x, rc = 0x%x\n", + __func__, __LINE__, opcode, GET_OPCODE_TYPE(opcode), cookie, event->status, rc); + return rc; +} + +/** + * bnxt_qplib_rcfw_send_message - qplib interface to send + * and complete rcfw command. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * Driver interact with Firmware through rcfw channel/slow path in two ways. + * a. Blocking rcfw command send. In this path, driver cannot hold + * the context for longer period since it is holding cpu until + * command is not completed. + * b. Non-blocking rcfw command send. In this path, driver can hold the + * context for longer period. There may be many pending command waiting + * for completion because of non-blocking nature. + * + * Driver will use shadow queue depth. Current queue depth of 8K + * (due to size of rcfw message it can be actual ~4K rcfw outstanding) + * is not optimal for rcfw command processing in firmware. + * RCFW_CMD_NON_BLOCKING_SHADOW_QD is defined as 64. + * Restrict at max 64 Non-Blocking rcfw commands. + * Do not allow more than 64 non-blocking command to the Firmware. + * Allow all blocking commands until there is no queue full. + * + * Returns: + * 0 if command completed by firmware. + * Non zero if the command is not completed by firmware. + */ +int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) +{ + int ret; + + if (!msg->block) { + down(&rcfw->rcfw_inflight); + ret = __bnxt_qplib_rcfw_send_message(rcfw, msg); + up(&rcfw->rcfw_inflight); + } else { + ret = __bnxt_qplib_rcfw_send_message(rcfw, msg); + } + + return ret; +} + +static void bnxt_re_add_perf_stats(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_crsqe *crsqe) +{ + u32 latency_msec, dest_stats_id; + u64 *dest_stats_ptr = NULL; + + latency_msec = jiffies_to_msecs(rcfw->cmdq.last_seen - + crsqe->send_timestamp); + if (latency_msec/1000 < RCFW_MAX_LATENCY_SEC_SLAB_INDEX) + rcfw->rcfw_lat_slab_sec[latency_msec/1000]++; + + if (!rcfw->sp_perf_stats_enabled) + return; + + if (latency_msec < RCFW_MAX_LATENCY_MSEC_SLAB_INDEX) + rcfw->rcfw_lat_slab_msec[latency_msec]++; + + switch (crsqe->opcode) { + case CMDQ_BASE_OPCODE_CREATE_QP: + dest_stats_id = rcfw->qp_create_stats_id++; + dest_stats_id = dest_stats_id % RCFW_MAX_STAT_INDEX; + dest_stats_ptr = &rcfw->qp_create_stats[dest_stats_id]; + break; + case CMDQ_BASE_OPCODE_DESTROY_QP: + dest_stats_id = rcfw->qp_destroy_stats_id++; + dest_stats_id = dest_stats_id % RCFW_MAX_STAT_INDEX; + dest_stats_ptr = &rcfw->qp_destroy_stats[dest_stats_id]; + break; + case CMDQ_BASE_OPCODE_REGISTER_MR: + dest_stats_id = rcfw->mr_create_stats_id++; + dest_stats_id = dest_stats_id % RCFW_MAX_STAT_INDEX; + dest_stats_ptr = &rcfw->mr_create_stats[dest_stats_id]; + break; + case CMDQ_BASE_OPCODE_DEREGISTER_MR: + case CMDQ_BASE_OPCODE_DEALLOCATE_KEY: + dest_stats_id = rcfw->mr_destroy_stats_id++; + dest_stats_id = dest_stats_id % RCFW_MAX_STAT_INDEX; + dest_stats_ptr = &rcfw->mr_destroy_stats[dest_stats_id]; + break; + case CMDQ_BASE_OPCODE_MODIFY_QP: + if (crsqe->requested_qp_state != IB_QPS_ERR) + break; + dest_stats_id = rcfw->qp_modify_stats_id++; + dest_stats_id = dest_stats_id % RCFW_MAX_STAT_INDEX; + dest_stats_ptr = &rcfw->qp_modify_stats[dest_stats_id]; + break; + default: + break; + } + if (dest_stats_ptr) + *dest_stats_ptr = max_t(unsigned long, + (rcfw->cmdq.last_seen - crsqe->send_timestamp), 1); + +} + +/* Completions */ +static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, + struct creq_qp_event *event, + u32 *num_wait) +{ + struct bnxt_qplib_hwq *cmdq_hwq = &rcfw->cmdq.hwq; + struct creq_cq_error_notification *cqerr; + struct creq_qp_error_notification *qperr; + struct bnxt_qplib_crsqe *crsqe; + struct bnxt_qplib_reftbl *tbl; + struct bnxt_qplib_qp *qp; + struct bnxt_qplib_cq *cq; + u16 cookie, blocked = 0; + struct pci_dev *pdev; + bool is_waiter_alive; + unsigned long flags; + u32 wait_cmds = 0; + u32 xid, qp_idx; + u32 req_size; + int rc = 0; + + pdev = rcfw->pdev; + switch (event->event) { + case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION: + tbl = &rcfw->res->reftbl.qpref; + qperr = (struct creq_qp_error_notification *)event; + xid = le32_to_cpu(qperr->xid); + qp_idx = map_qp_id_to_tbl_indx(xid, tbl); + spin_lock(&tbl->lock); + qp = tbl->rec[qp_idx].handle; + if (!qp) { + spin_unlock(&tbl->lock); + break; + } + bnxt_qplib_mark_qp_error(qp); + rc = rcfw->creq.aeq_handler(rcfw, event, qp); + spin_unlock(&tbl->lock); + /* + * Keeping these prints as debug to avoid flooding of log + * messages during modify QP to error state by applications + */ + dev_dbg(&pdev->dev, "QPLIB: QP Error encountered!\n"); + dev_dbg(&pdev->dev, + "QPLIB: qpid 0x%x, req_err=0x%x, resp_err=0x%x\n", + xid, qperr->req_err_state_reason, + qperr->res_err_state_reason); + break; + case CREQ_QP_EVENT_EVENT_CQ_ERROR_NOTIFICATION: + tbl = &rcfw->res->reftbl.cqref; + cqerr = (struct creq_cq_error_notification *)event; + xid = le32_to_cpu(cqerr->xid); + spin_lock(&tbl->lock); + cq = tbl->rec[GET_TBL_INDEX(xid, tbl)].handle; + if (!cq) { + spin_unlock(&tbl->lock); + break; + } + rc = rcfw->creq.aeq_handler(rcfw, event, cq); + spin_unlock(&tbl->lock); + dev_dbg(&pdev->dev, "QPLIB: CQ error encountered!\n"); + break; + default: + /* + * Command Response + * cmdq hwq lock needs to be acquired to synchronize + * the command send and completion reaping. This function + * is always called with creq hwq lock held. So there is no + * chance of deadlock here as the locking is in correct sequence. + * Using the nested variant of spin_lock to annotate + */ + spin_lock_irqsave_nested(&cmdq_hwq->lock, flags, + SINGLE_DEPTH_NESTING); + cookie = le16_to_cpu(event->cookie); + blocked = cookie & RCFW_CMD_IS_BLOCKING; + cookie &= RCFW_MAX_COOKIE_VALUE; + + crsqe = &rcfw->crsqe_tbl[cookie]; + + bnxt_re_add_perf_stats(rcfw, crsqe); + + if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED, + &rcfw->cmdq.flags), + "QPLIB: Unreponsive rcfw channel detected.!!")) { + dev_info(&pdev->dev, "rcfw timedout: cookie = %#x," + " latency_msec = %ld free_slots = %d\n", cookie, + (long)jiffies_to_msecs(rcfw->cmdq.last_seen - + crsqe->send_timestamp), + crsqe->free_slots); + spin_unlock_irqrestore(&cmdq_hwq->lock, flags); + return rc; + } + + if (crsqe->is_internal_cmd && !event->status) + atomic_dec(&rcfw->timeout_send); + + if (crsqe->is_waiter_alive) { + if (crsqe->resp) + memcpy(crsqe->resp, event, sizeof(*event)); + if (!blocked) + wait_cmds++; + } + + req_size = crsqe->req_size; + is_waiter_alive = crsqe->is_waiter_alive; + + crsqe->req_size = 0; + if (!crsqe->is_waiter_alive) + crsqe->resp = NULL; + crsqe->is_in_used = false; + /* Consumer is updated so that __send_message_no_waiter + * can never see queue full. + * It is safe since we are still holding cmdq_hwq->lock. + */ + cmdq_hwq->cons += req_size; + + /* This is a case to handle below scenario - + * Create AH is completed successfully by firmware, + * but completion took more time and driver already lost + * the context of create_ah from caller. + * We have already return failure for create_ah verbs, + * so let's destroy the same address vector since it is + * no more used in stack. We don't care about completion + * in __send_message_no_waiter. + * If destroy_ah is failued by firmware, there will be AH + * resource leak and relatively not critical + unlikely + * scenario. Current design is not to handle such case. + */ + if (!is_waiter_alive && !event->status && + event->event == CREQ_QP_EVENT_EVENT_CREATE_AH) + __destroy_timedout_ah(rcfw, + (struct creq_create_ah_resp *) + event); + + spin_unlock_irqrestore(&cmdq_hwq->lock, flags); + } + *num_wait += wait_cmds; + return rc; +} + +/* SP - CREQ Completion handlers */ +static void bnxt_qplib_service_creq(unsigned long data) +{ + struct bnxt_qplib_rcfw *rcfw = (struct bnxt_qplib_rcfw *)data; + struct bnxt_qplib_creq_ctx *creq = &rcfw->creq; + struct bnxt_qplib_res *res; + u32 type, budget = CREQ_ENTRY_POLL_BUDGET; + struct bnxt_qplib_hwq *creq_hwq = &creq->hwq; + struct creq_base *creqe; + struct pci_dev *pdev; + unsigned long flags; + u32 num_wakeup = 0; + int rc; + + pdev = rcfw->pdev; + res = rcfw->res; + /* Service the CREQ until empty */ + spin_lock_irqsave(&creq_hwq->lock, flags); + while (budget > 0) { + if (RCFW_NO_FW_ACCESS(rcfw)) { + spin_unlock_irqrestore(&creq_hwq->lock, flags); + return; + } + creqe = bnxt_qplib_get_qe(creq_hwq, creq_hwq->cons, NULL); + if (!CREQ_CMP_VALID(creqe, creq->creq_db.dbinfo.flags)) + break; + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + type = creqe->type & CREQ_BASE_TYPE_MASK; + rcfw->cmdq.last_seen = jiffies; + + switch (type) { + case CREQ_BASE_TYPE_QP_EVENT: + bnxt_qplib_process_qp_event + (rcfw,(struct creq_qp_event *)creqe, + &num_wakeup); + creq->stats.creq_qp_event_processed++; + break; + case CREQ_BASE_TYPE_FUNC_EVENT: + rc = rcfw->creq.aeq_handler(rcfw, creqe, NULL); + if (rc) + dev_warn(&pdev->dev, + "QPLIB: async event type = 0x%x not handled", + type); + creq->stats.creq_func_event_processed++; + break; + default: + if (type != HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT) { + dev_warn(&pdev->dev, + "QPLIB: op_event = 0x%x not handled\n", + type); + } + break; + } + budget--; + bnxt_qplib_hwq_incr_cons(creq_hwq->max_elements, &creq_hwq->cons, + 1, &creq->creq_db.dbinfo.flags); + } + if (budget == CREQ_ENTRY_POLL_BUDGET && + !CREQ_CMP_VALID(creqe, creq->creq_db.dbinfo.flags)) { + /* No completions received during this poll. Enable interrupt now */ + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true); + creq->stats.creq_arm_count++; + dev_dbg(&pdev->dev, "QPLIB: Num of Func (0x%llx) \n", + creq->stats.creq_func_event_processed); + dev_dbg(&pdev->dev, "QPLIB: QP (0x%llx) events processed\n", + creq->stats.creq_qp_event_processed); + dev_dbg(&pdev->dev, "QPLIB: Armed:%#llx resched:%#llx \n", + creq->stats.creq_arm_count, + creq->stats.creq_tasklet_schedule_count); + } else if (creq->requested) { + /* + * Currently there is no bottom half implementation to process + * completions, all completions are processed in interrupt context + * only. So enable interrupts. + */ + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true); + creq->stats.creq_tasklet_schedule_count++; + } + spin_unlock_irqrestore(&creq_hwq->lock, flags); + if (num_wakeup) + wake_up_all(&rcfw->cmdq.waitq); +} + +static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance) +{ + struct bnxt_qplib_rcfw *rcfw = dev_instance; + + bnxt_qplib_service_creq((unsigned long)rcfw); + return IRQ_HANDLED; +} + +/* RCFW */ +int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw) +{ + struct creq_deinitialize_fw_resp resp = {}; + struct cmdq_deinitialize_fw req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DEINITIALIZE_FW, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, + sizeof(req), sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->cmdq.flags); + return 0; +} + +int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, int is_virtfn) +{ + struct creq_initialize_fw_resp resp = {}; + struct cmdq_initialize_fw req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_qplib_ctx *hctx; + struct bnxt_qplib_res *res; + struct bnxt_qplib_hwq *hwq; + int rc; + + res = rcfw->res; + cctx = res->cctx; + hctx = res->hctx; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_INITIALIZE_FW, + sizeof(req)); + /* Supply (log-base-2-of-host-page-size - base-page-shift) + * to bono to adjust the doorbell page sizes. + */ + req.log2_dbr_pg_size = cpu_to_le16(PAGE_SHIFT - + RCFW_DBR_BASE_PAGE_SHIFT); + /* + * VFs need not setup the HW context area, PF + * shall setup this area for VF. Skipping the + * HW programming + */ + if (is_virtfn || _is_chip_gen_p5_p7(cctx)) + goto skip_ctx_setup; + + hwq = &hctx->qp_ctx.hwq; + req.qpc_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.number_of_qp = cpu_to_le32(hwq->max_elements); + req.qpc_pg_size_qpc_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_QPC_PG_SIZE_SFT) | + (u8)hwq->level; + + hwq = &hctx->mrw_ctx.hwq; + req.mrw_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.number_of_mrw = cpu_to_le32(hwq->max_elements); + req.mrw_pg_size_mrw_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_MRW_PG_SIZE_SFT) | + (u8)hwq->level; + + hwq = &hctx->srq_ctx.hwq; + req.srq_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.number_of_srq = cpu_to_le32(hwq->max_elements); + req.srq_pg_size_srq_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_SRQ_PG_SIZE_SFT) | + (u8)hwq->level; + + hwq = &hctx->cq_ctx.hwq; + req.cq_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.number_of_cq = cpu_to_le32(hwq->max_elements); + req.cq_pg_size_cq_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_CQ_PG_SIZE_SFT) | + (u8)hwq->level; + + hwq = &hctx->tim_ctx.hwq; + req.tim_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.tim_pg_size_tim_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_TIM_PG_SIZE_SFT) | + (u8)hwq->level; + hwq = &hctx->tqm_ctx.pde; + req.tqm_page_dir = cpu_to_le64(_get_base_addr(hwq)); + req.tqm_pg_size_tqm_lvl = (_get_pte_pg_size(hwq) << + CMDQ_INITIALIZE_FW_TQM_PG_SIZE_SFT) | + (u8)hwq->level; +skip_ctx_setup: + if (BNXT_RE_HW_RETX(res->dattr->dev_cap_flags)) + req.flags |= CMDQ_INITIALIZE_FW_FLAGS_HW_REQUESTER_RETX_SUPPORTED; + req.stat_ctx_id = cpu_to_le32(hctx->stats.fw_id); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, + sizeof(req), sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->cmdq.flags); + + return 0; +} + +void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + + vfree(rcfw->rcfw_lat_slab_msec); + rcfw->rcfw_lat_slab_msec = NULL; + vfree(rcfw->qp_create_stats); + rcfw->qp_create_stats = NULL; + vfree(rcfw->qp_destroy_stats); + rcfw->qp_destroy_stats = NULL; + vfree(rcfw->mr_create_stats); + rcfw->mr_create_stats = NULL; + vfree(rcfw->mr_destroy_stats); + rcfw->mr_destroy_stats = NULL; + vfree(rcfw->qp_modify_stats); + rcfw->qp_modify_stats = NULL; + rcfw->sp_perf_stats_enabled = false; + + kfree(rcfw->crsqe_tbl); + rcfw->crsqe_tbl = NULL; + + bnxt_qplib_free_hwq(res, &rcfw->cmdq.hwq); + bnxt_qplib_free_hwq(res, &rcfw->creq.hwq); + rcfw->pdev = NULL; +} + +int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct bnxt_qplib_sg_info sginfo = {}; + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_creq_ctx *creq; + + rcfw->pdev = res->pdev; + rcfw->res = res; + cmdq = &rcfw->cmdq; + creq = &rcfw->creq; + + sginfo.pgsize = PAGE_SIZE; + sginfo.pgshft = PAGE_SHIFT; + + hwq_attr.sginfo = &sginfo; + hwq_attr.res = rcfw->res; + hwq_attr.depth = BNXT_QPLIB_CREQE_MAX_CNT; + hwq_attr.stride = BNXT_QPLIB_CREQE_UNITS; + hwq_attr.type = _get_hwq_type(res); + + if (bnxt_qplib_alloc_init_hwq(&creq->hwq, &hwq_attr)) { + dev_err(&rcfw->pdev->dev, + "QPLIB: HW channel CREQ allocation failed\n"); + return -ENOMEM; + } + + sginfo.pgsize = BNXT_QPLIB_CMDQE_PAGE_SIZE; + hwq_attr.depth = BNXT_QPLIB_CMDQE_MAX_CNT & 0x7FFFFFFF; + hwq_attr.stride = BNXT_QPLIB_CMDQE_UNITS; + hwq_attr.type = HWQ_TYPE_CTX; + if (bnxt_qplib_alloc_init_hwq(&cmdq->hwq, &hwq_attr)) { + dev_err(&rcfw->pdev->dev, + "QPLIB: HW channel CMDQ allocation failed\n"); + goto fail_free_creq_hwq; + } + + rcfw->crsqe_tbl = kcalloc(cmdq->hwq.max_elements, + sizeof(*rcfw->crsqe_tbl), GFP_KERNEL); + if (!rcfw->crsqe_tbl) { + dev_err(&rcfw->pdev->dev, + "QPLIB: HW channel CRSQ allocation failed\n"); + goto fail_free_cmdq_hwq; + } + + rcfw->max_timeout = res->cctx->hwrm_cmd_max_timeout; + + rcfw->sp_perf_stats_enabled = false; + rcfw->rcfw_lat_slab_msec = vzalloc(sizeof(u32) * + RCFW_MAX_LATENCY_MSEC_SLAB_INDEX); + rcfw->qp_create_stats = vzalloc(sizeof(u64) * RCFW_MAX_STAT_INDEX); + rcfw->qp_destroy_stats = vzalloc(sizeof(u64) * RCFW_MAX_STAT_INDEX); + rcfw->mr_create_stats = vzalloc(sizeof(u64) * RCFW_MAX_STAT_INDEX); + rcfw->mr_destroy_stats = vzalloc(sizeof(u64) * RCFW_MAX_STAT_INDEX); + rcfw->qp_modify_stats = vzalloc(sizeof(u64) * RCFW_MAX_STAT_INDEX); + + if (rcfw->rcfw_lat_slab_msec && + rcfw->qp_create_stats && + rcfw->qp_destroy_stats && + rcfw->mr_create_stats && + rcfw->mr_destroy_stats && + rcfw->qp_modify_stats) + rcfw->sp_perf_stats_enabled = true; + + return 0; +fail_free_cmdq_hwq: + bnxt_qplib_free_hwq(res, &rcfw->cmdq.hwq); +fail_free_creq_hwq: + bnxt_qplib_free_hwq(res, &rcfw->creq.hwq); + return -ENOMEM; +} + +void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill) +{ + struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_res *res; + + creq = &rcfw->creq; + res = rcfw->res; + + if (!creq->requested) + return; + + creq->requested = false; + /* Mask h/w interrupts */ + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, false); + /* Sync with last running IRQ-handler */ + synchronize_irq(creq->msix_vec); + free_irq(creq->msix_vec, rcfw); + kfree(creq->irq_name); + creq->irq_name = NULL; + /* rcfw_intr_enabled should not be greater than 1. Debug + * print to check if that is the case + */ + if (atomic_read(&rcfw->rcfw_intr_enabled) > 1) { + dev_err(&rcfw->pdev->dev, + "%s: rcfw->rcfw_intr_enabled = 0x%x\n", __func__, + atomic_read(&rcfw->rcfw_intr_enabled)); + } + atomic_set(&rcfw->rcfw_intr_enabled, 0); + rcfw->num_irq_stopped++; +} + +void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) +{ + struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_cmdq_ctx *cmdq; + + creq = &rcfw->creq; + cmdq = &rcfw->cmdq; + /* Make sure the HW channel is stopped! */ + bnxt_qplib_rcfw_stop_irq(rcfw, true); + + creq->creq_db.reg.bar_reg = NULL; + creq->creq_db.db = NULL; + + if (cmdq->cmdq_mbox.reg.bar_reg) { + iounmap(cmdq->cmdq_mbox.reg.bar_reg); + cmdq->cmdq_mbox.reg.bar_reg = NULL; + cmdq->cmdq_mbox.prod = NULL; + cmdq->cmdq_mbox.db = NULL; + } + + creq->aeq_handler = NULL; + creq->msix_vec = 0; +} + +int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, + bool need_init) +{ + struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_res *res; + int rc; + + creq = &rcfw->creq; + res = rcfw->res; + + if (creq->requested) + return -EFAULT; + + creq->msix_vec = msix_vector; + + creq->irq_name = kasprintf(GFP_KERNEL, "bnxt_re-creq@pci:%s\n", + pci_name(res->pdev)); + if (!creq->irq_name) + return -ENOMEM; + + rc = request_irq(creq->msix_vec, bnxt_qplib_creq_irq, 0, + creq->irq_name, rcfw); + if (rc) { + kfree(creq->irq_name); + creq->irq_name = NULL; + return rc; + } + creq->requested = true; + + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true); + + rcfw->num_irq_started++; + /* Debug print to check rcfw interrupt enable/disable is invoked + * out of sequence + */ + if (atomic_read(&rcfw->rcfw_intr_enabled) > 0) { + dev_err(&rcfw->pdev->dev, + "%s: rcfw->rcfw_intr_enabled = 0x%x\n", __func__, + atomic_read(&rcfw->rcfw_intr_enabled)); + } + atomic_inc(&rcfw->rcfw_intr_enabled); + return 0; +} + +static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw) +{ + struct bnxt_qplib_cmdq_mbox *mbox; + resource_size_t bar_reg; + struct pci_dev *pdev; + + pdev = rcfw->pdev; + mbox = &rcfw->cmdq.cmdq_mbox; + + mbox->reg.bar_id = RCFW_COMM_PCI_BAR_REGION; + mbox->reg.len = RCFW_COMM_SIZE; + mbox->reg.bar_base = pci_resource_start(pdev, mbox->reg.bar_id); + if (!mbox->reg.bar_base) { + dev_err(&pdev->dev, + "QPLIB: CMDQ BAR region %d resc start is 0!\n", + mbox->reg.bar_id); + return -ENOMEM; + } + + bar_reg = mbox->reg.bar_base + RCFW_COMM_BASE_OFFSET; + mbox->reg.len = RCFW_COMM_SIZE; + mbox->reg.bar_reg = ioremap(bar_reg, mbox->reg.len); + if (!mbox->reg.bar_reg) { + dev_err(&pdev->dev, + "QPLIB: CMDQ BAR region %d mapping failed\n", + mbox->reg.bar_id); + return -ENOMEM; + } + + mbox->prod = (void __iomem *)((char *)mbox->reg.bar_reg + + RCFW_PF_VF_COMM_PROD_OFFSET); + mbox->db = (void __iomem *)((char *)mbox->reg.bar_reg + + RCFW_COMM_TRIG_OFFSET); + return 0; +} + +static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt) +{ + struct bnxt_qplib_creq_db *creq_db; + struct bnxt_qplib_reg_desc *dbreg; + struct bnxt_qplib_res *res; + + res = rcfw->res; + creq_db = &rcfw->creq.creq_db; + dbreg = &res->dpi_tbl.ucreg; + + creq_db->reg.bar_id = dbreg->bar_id; + creq_db->reg.bar_base = dbreg->bar_base; + creq_db->reg.bar_reg = dbreg->bar_reg + reg_offt; + creq_db->reg.len = _is_chip_gen_p5_p7(res->cctx) ? sizeof(u64) : + sizeof(u32); + + creq_db->dbinfo.db = creq_db->reg.bar_reg; + creq_db->dbinfo.hwq = &rcfw->creq.hwq; + creq_db->dbinfo.xid = rcfw->creq.ring_id; + creq_db->dbinfo.seed = rcfw->creq.ring_id; + creq_db->dbinfo.flags = 0; + spin_lock_init(&creq_db->dbinfo.lock); + creq_db->dbinfo.shadow_key = BNXT_QPLIB_DBR_KEY_INVALID; + creq_db->dbinfo.res = rcfw->res; + + return 0; +} + +static void bnxt_qplib_start_rcfw(struct bnxt_qplib_rcfw *rcfw) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_cmdq_mbox *mbox; + struct cmdq_init init = {0}; + + cmdq = &rcfw->cmdq; + creq = &rcfw->creq; + mbox = &cmdq->cmdq_mbox; + + init.cmdq_pbl = cpu_to_le64(cmdq->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); + init.cmdq_size_cmdq_lvl = cpu_to_le16( + ((BNXT_QPLIB_CMDQE_MAX_CNT << CMDQ_INIT_CMDQ_SIZE_SFT) & + CMDQ_INIT_CMDQ_SIZE_MASK) | + ((cmdq->hwq.level << CMDQ_INIT_CMDQ_LVL_SFT) & + CMDQ_INIT_CMDQ_LVL_MASK)); + init.creq_ring_id = cpu_to_le16(creq->ring_id); + /* Write to the Bono mailbox register */ + __iowrite32_copy(mbox->reg.bar_reg, &init, sizeof(init) / 4); +} + +int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, + int msix_vector, + int cp_bar_reg_off, + aeq_handler_t aeq_handler) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_creq_ctx *creq; + int rc; + + cmdq = &rcfw->cmdq; + creq = &rcfw->creq; + + /* Clear to defaults */ + cmdq->seq_num = 0; + set_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags); + init_waitqueue_head(&cmdq->waitq); + + creq->stats.creq_qp_event_processed = 0; + creq->stats.creq_func_event_processed = 0; + creq->aeq_handler = aeq_handler; + + rc = bnxt_qplib_map_cmdq_mbox(rcfw); + if (rc) + return rc; + + rc = bnxt_qplib_map_creq_db(rcfw, cp_bar_reg_off); + if (rc) + return rc; + + rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_vector, true); + if (rc) { + dev_err(&rcfw->pdev->dev, + "QPLIB: Failed to request IRQ for CREQ rc = 0x%x\n", rc); + bnxt_qplib_disable_rcfw_channel(rcfw); + return rc; + } + + rcfw->curr_shadow_qd = min_not_zero(cmdq_shadow_qd, + (unsigned int)RCFW_CMD_NON_BLOCKING_SHADOW_QD); + sema_init(&rcfw->rcfw_inflight, rcfw->curr_shadow_qd); + dev_dbg(&rcfw->pdev->dev, + "Perf Debug: shadow qd %d\n", rcfw->curr_shadow_qd); + bnxt_qplib_start_rcfw(rcfw); + + return 0; +} diff --git a/sys/dev/bnxt/bnxt_re/qplib_rcfw.h b/sys/dev/bnxt/bnxt_re/qplib_rcfw.h new file mode 100644 index 000000000000..f117525daacb --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_rcfw.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: RDMA Controller HW interface (header) + */ + +#ifndef __BNXT_QPLIB_RCFW_H__ +#define __BNXT_QPLIB_RCFW_H__ + +#include <linux/semaphore.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/mutex.h> +#include <linux/list.h> +#include <linux/rculist.h> +#include <linux/spinlock.h> +#include <linux/pci.h> +#include <net/ipv6.h> +#include <linux/if_ether.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/interrupt.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> + +#include "qplib_tlv.h" + +#define RCFW_CMDQ_TRIG_VAL 1 +#define RCFW_COMM_PCI_BAR_REGION 0 +#define RCFW_COMM_CONS_PCI_BAR_REGION 2 +#define RCFW_COMM_BASE_OFFSET 0x600 +#define RCFW_PF_VF_COMM_PROD_OFFSET 0xc +#define RCFW_COMM_TRIG_OFFSET 0x100 +#define RCFW_COMM_SIZE 0x104 + +#define RCFW_DBR_PCI_BAR_REGION 2 +#define RCFW_DBR_BASE_PAGE_SHIFT 12 +#define RCFW_MAX_LATENCY_SEC_SLAB_INDEX 128 +#define RCFW_MAX_LATENCY_MSEC_SLAB_INDEX 3000 +#define RCFW_MAX_STAT_INDEX 0xFFFF +#define RCFW_FW_STALL_MAX_TIMEOUT 40 + +#define GET_OPCODE_TYPE(x) \ + ((x) == 0x1 ? "CREATE_QP": \ + ((x) == 0x2 ? "DESTROY_QP": \ + ((x) == 0x3 ? "MODIFY_QP": \ + ((x) == 0x4 ? "QUERY_QP": \ + ((x) == 0x5 ? "CREATE_SRQ": \ + ((x) == 0x6 ? "DESTROY_SRQ": \ + ((x) == 0x8 ? "QUERY_SRQ": \ + ((x) == 0x9 ? "CREATE_CQ": \ + ((x) == 0xa ? "DESTROY_CQ": \ + ((x) == 0xc ? "RESIZE_CQ": \ + ((x) == 0xd ? "ALLOCATE_MRW": \ + ((x) == 0xe ? "DEALLOCATE_KEY": \ + ((x) == 0xf ? "REGISTER_MR": \ + ((x) == 0x10 ? "DEREGISTER_MR": \ + ((x) == 0x11 ? "ADD_GID": \ + ((x) == 0x12 ? "DELETE_GID": \ + ((x) == 0x17 ? "MODIFY_GID": \ + ((x) == 0x18 ? "QUERY_GID": \ + ((x) == 0x13 ? "CREATE_QP1": \ + ((x) == 0x14 ? "DESTROY_QP1": \ + ((x) == 0x15 ? "CREATE_AH": \ + ((x) == 0x16 ? "DESTROY_AH": \ + ((x) == 0x80 ? "INITIALIZE_FW": \ + ((x) == 0x81 ? "DEINITIALIZE_FW": \ + ((x) == 0x82 ? "STOP_FUNC": \ + ((x) == 0x83 ? "QUERY_FUNC": \ + ((x) == 0x84 ? "SET_FUNC_RESOURCES": \ + ((x) == 0x85 ? "READ_CONTEXT": \ + ((x) == 0x86 ? "VF_BACKCHANNEL_REQUEST": \ + ((x) == 0x87 ? "READ_VF_MEMORY": \ + ((x) == 0x88 ? "COMPLETE_VF_REQUEST": \ + ((x) == 0x89 ? "EXTEND_CONTEXT_ARRRAY": \ + ((x) == 0x8a ? "MAP_TC_TO_COS": \ + ((x) == 0x8b ? "QUERY_VERSION": \ + ((x) == 0x8c ? "MODIFY_ROCE_CC": \ + ((x) == 0x8d ? "QUERY_ROCE_CC": \ + ((x) == 0x8e ? "QUERY_ROCE_STATS": \ + ((x) == 0x8f ? "SET_LINK_AGGR_MODE": \ + ((x) == 0x90 ? "MODIFY_CQ": \ + ((x) == 0x91 ? "QUERY_QP_EXTEND": \ + ((x) == 0x92 ? "QUERY_ROCE_STATS_EXT": \ + "Unknown OPCODE" \ + ))))))))))))))))))))))))))))))))))))))))) + +extern unsigned int cmdq_shadow_qd; +/* Cmdq contains a fix number of a 16-Byte slots */ +struct bnxt_qplib_cmdqe { + u8 data[16]; +}; +#define BNXT_QPLIB_CMDQE_UNITS sizeof(struct bnxt_qplib_cmdqe) + +static inline void bnxt_qplib_rcfw_cmd_prep(void *r, u8 opcode, u8 cmd_size) +{ + struct cmdq_base *req = r; + + req->opcode = opcode; + req->cmd_size = cmd_size; +} + +/* Shadow queue depth for non blocking command */ +#define RCFW_CMD_NON_BLOCKING_SHADOW_QD 64 +#define RCFW_CMD_DEV_ERR_CHECK_TIME_MS 1000 /* 1 Second time out*/ +#define RCFW_ERR_RETRY_COUNT (RCFW_CMD_WAIT_TIME_MS / RCFW_CMD_DEV_ERR_CHECK_TIME_MS) + +/* CMDQ elements */ +#define BNXT_QPLIB_CMDQE_MAX_CNT 8192 +#define BNXT_QPLIB_CMDQE_BYTES (BNXT_QPLIB_CMDQE_MAX_CNT * \ + BNXT_QPLIB_CMDQE_UNITS) +#define BNXT_QPLIB_CMDQE_NPAGES ((BNXT_QPLIB_CMDQE_BYTES % \ + PAGE_SIZE) ? \ + ((BNXT_QPLIB_CMDQE_BYTES / \ + PAGE_SIZE) + 1) : \ + (BNXT_QPLIB_CMDQE_BYTES / \ + PAGE_SIZE)) +#define BNXT_QPLIB_CMDQE_PAGE_SIZE (BNXT_QPLIB_CMDQE_NPAGES * \ + PAGE_SIZE) + +#define RCFW_MAX_OUTSTANDING_CMD BNXT_QPLIB_CMDQE_MAX_CNT +#define RCFW_MAX_COOKIE_VALUE (BNXT_QPLIB_CMDQE_MAX_CNT - 1) +#define RCFW_CMD_IS_BLOCKING 0x8000 +#define RCFW_NO_FW_ACCESS(rcfw) \ + (test_bit(ERR_DEVICE_DETACHED, &(rcfw)->cmdq.flags) || \ + pci_channel_offline((rcfw)->pdev)) + +/* Crsq buf is 1024-Byte */ +struct bnxt_qplib_crsbe { + u8 data[1024]; +}; + +/* Get the number of command units required for the req. The + * function returns correct value only if called before + * setting using bnxt_qplib_set_cmd_slots + */ +static inline u32 bnxt_qplib_get_cmd_slots(struct cmdq_base *req) +{ + u32 cmd_units = 0; + + if (HAS_TLV_HEADER(req)) { + struct roce_tlv *tlv_req = (struct roce_tlv *)req; + cmd_units = tlv_req->total_size; + } else { + cmd_units = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) / + BNXT_QPLIB_CMDQE_UNITS; + } + return cmd_units; +} + +/* Set the cmd_size to a factor of CMDQE unit */ +static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req) +{ + u32 cmd_byte = 0; + + if (HAS_TLV_HEADER(req)) { + struct roce_tlv *tlv_req = (struct roce_tlv *)req; + cmd_byte = tlv_req->total_size * BNXT_QPLIB_CMDQE_UNITS; + } else { + cmd_byte = req->cmd_size; + req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) / + BNXT_QPLIB_CMDQE_UNITS; + } + + return cmd_byte; +} + +/* CREQ */ +/* Allocate 1 per QP for async error notification for now */ +#define BNXT_QPLIB_CREQE_MAX_CNT (64 * 1024) +#define BNXT_QPLIB_CREQE_UNITS 16 /* 16-Bytes per prod unit */ + +#define CREQ_CMP_VALID(hdr, pass) \ + (!!((hdr)->v & CREQ_BASE_V) == \ + !(pass & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK)) + +#define CREQ_ENTRY_POLL_BUDGET 8 + +typedef int (*aeq_handler_t)(struct bnxt_qplib_rcfw *, void *, void *); + +struct bnxt_qplib_crsqe { + struct creq_qp_event *resp; + u32 req_size; + bool is_waiter_alive; + bool is_internal_cmd; + bool is_in_used; + + /* Free slots at the time of submission */ + u32 free_slots; + unsigned long send_timestamp; + u8 opcode; + u8 requested_qp_state; +}; + +struct bnxt_qplib_rcfw_sbuf { + void *sb; + dma_addr_t dma_addr; + u32 size; +}; + +#define BNXT_QPLIB_OOS_COUNT_MASK 0xFFFFFFFF + +#define FIRMWARE_INITIALIZED_FLAG (0) +#define FIRMWARE_FIRST_FLAG (31) +#define FIRMWARE_STALL_DETECTED (3) +#define ERR_DEVICE_DETACHED (4) +struct bnxt_qplib_cmdq_mbox { + struct bnxt_qplib_reg_desc reg; + void __iomem *prod; + void __iomem *db; +}; + +struct bnxt_qplib_cmdq_ctx { + struct bnxt_qplib_hwq hwq; + struct bnxt_qplib_cmdq_mbox cmdq_mbox; + wait_queue_head_t waitq; + unsigned long flags; + unsigned long last_seen; + u32 seq_num; +}; + +struct bnxt_qplib_creq_db { + struct bnxt_qplib_reg_desc reg; + void __iomem *db; + struct bnxt_qplib_db_info dbinfo; +}; + +struct bnxt_qplib_creq_stat { + u64 creq_arm_count; + u64 creq_tasklet_schedule_count; + u64 creq_qp_event_processed; + u64 creq_func_event_processed; +}; + +struct bnxt_qplib_creq_ctx { + struct bnxt_qplib_hwq hwq; + struct bnxt_qplib_creq_db creq_db; + struct bnxt_qplib_creq_stat stats; + aeq_handler_t aeq_handler; + u16 ring_id; + int msix_vec; + bool requested; + char *irq_name; +}; + +/* RCFW Communication Channels */ +#define BNXT_QPLIB_RCFW_SEND_RETRY_COUNT 4000 +struct bnxt_qplib_rcfw { + struct pci_dev *pdev; + struct bnxt_qplib_res *res; + struct bnxt_qplib_cmdq_ctx cmdq; + struct bnxt_qplib_creq_ctx creq; + struct bnxt_qplib_crsqe *crsqe_tbl; + u32 rcfw_lat_slab_sec[RCFW_MAX_LATENCY_SEC_SLAB_INDEX]; + + /* Slow path Perf Stats */ + bool sp_perf_stats_enabled; + u32 *rcfw_lat_slab_msec; + u64 *qp_create_stats; + u64 *qp_destroy_stats; + u64 *qp_modify_stats; + u64 *mr_create_stats; + u64 *mr_destroy_stats; + u32 qp_create_stats_id; + u32 qp_destroy_stats_id; + u32 qp_modify_stats_id; + u32 mr_create_stats_id; + u32 mr_destroy_stats_id; + bool init_oos_stats; + u64 oos_prev; + u32 num_irq_stopped; + u32 num_irq_started; + u32 poll_in_intr_en; + u32 poll_in_intr_dis; + atomic_t rcfw_intr_enabled; + u32 cmdq_full_dbg; + struct semaphore rcfw_inflight; + unsigned int curr_shadow_qd; + atomic_t timeout_send; + /* cached from chip cctx for quick reference in slow path */ + u16 max_timeout; +}; + +struct bnxt_qplib_cmdqmsg { + struct cmdq_base *req; + struct creq_base *resp; + void *sb; + u32 req_sz; + u32 res_sz; + u8 block; + u8 qp_state; +}; + +static inline void bnxt_qplib_fill_cmdqmsg(struct bnxt_qplib_cmdqmsg *msg, + void *req, void *resp, void *sb, + u32 req_sz, u32 res_sz, u8 block) +{ + msg->req = req; + msg->resp = resp; + msg->sb = sb; + msg->req_sz = req_sz; + msg->res_sz = res_sz; + msg->block = block; +} + +void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_res *res); +int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res); +void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill); +void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw); +int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, + bool need_init); +int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, + int msix_vector, + int cp_bar_reg_off, + aeq_handler_t aeq_handler); + +struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf( + struct bnxt_qplib_rcfw *rcfw, + u32 size); +void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_rcfw_sbuf *sbuf); +int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg); + +int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw); +int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, int is_virtfn); +void bnxt_qplib_mark_qp_error(void *qp_handle); +int __check_cmdq_stall(struct bnxt_qplib_rcfw *rcfw, + u32 *cur_prod, u32 *cur_cons); +#endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_res.c b/sys/dev/bnxt/bnxt_re/qplib_res.c new file mode 100644 index 000000000000..69661c67708c --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_res.c @@ -0,0 +1,1226 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: QPLib resource manager + */ + +#include <linux/spinlock.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/inetdevice.h> +#include <linux/dma-mapping.h> +#include <linux/if_vlan.h> +#include <linux/vmalloc.h> + +#include <net/ipv6.h> +#include <rdma/ib_verbs.h> + +#include "hsi_struct_def.h" +#include "qplib_res.h" +#include "qplib_sp.h" +#include "qplib_rcfw.h" +#include "bnxt.h" +#include "bnxt_ulp.h" + +uint8_t _get_chip_gen_p5_type(struct bnxt_qplib_chip_ctx *cctx) +{ + /* Extend this for granular type */ + return(BNXT_RE_DEFAULT); +} + +inline bool _is_alloc_mr_unified(struct bnxt_qplib_dev_attr *dattr) +{ + return dattr->dev_cap_flags & + CREQ_QUERY_FUNC_RESP_SB_MR_REGISTER_ALLOC; +} + +/* PBL */ +static void __free_pbl(struct bnxt_qplib_res *res, + struct bnxt_qplib_pbl *pbl, bool is_umem) +{ + struct pci_dev *pdev; + int i; + + pdev = res->pdev; + if (is_umem == false) { + for (i = 0; i < pbl->pg_count; i++) { + if (pbl->pg_arr[i]) { + dma_free_coherent(&pdev->dev, pbl->pg_size, + (void *)((u64)pbl->pg_arr[i] & + PAGE_MASK), + pbl->pg_map_arr[i]); + } + else + dev_warn(&pdev->dev, + "QPLIB: PBL free pg_arr[%d] empty?!\n", + i); + pbl->pg_arr[i] = NULL; + } + } + + if (pbl->pg_arr) { + vfree(pbl->pg_arr); + pbl->pg_arr = NULL; + } + if (pbl->pg_map_arr) { + vfree(pbl->pg_map_arr); + pbl->pg_map_arr = NULL; + } + pbl->pg_count = 0; + pbl->pg_size = 0; +} + +struct qplib_sg { + dma_addr_t pg_map_arr; + u32 size; +}; + +static int __fill_user_dma_pages(struct bnxt_qplib_pbl *pbl, + struct bnxt_qplib_sg_info *sginfo) +{ + int sg_indx, pg_indx, tmp_size, offset; + struct qplib_sg *tmp_sg = NULL; + struct scatterlist *sg; + u64 pmask, addr; + + tmp_sg = vzalloc(sginfo->nmap * sizeof(struct qplib_sg)); + if (!tmp_sg) + return -ENOMEM; + + pmask = BIT_ULL(sginfo->pgshft) - 1; + sg_indx = 0; + for_each_sg(sginfo->sghead, sg, sginfo->nmap, sg_indx) { + tmp_sg[sg_indx].pg_map_arr = sg_dma_address(sg); + tmp_sg[sg_indx].size = sg_dma_len(sg); + } + pg_indx = 0; + for (sg_indx = 0; sg_indx < sginfo->nmap; sg_indx++) { + tmp_size = tmp_sg[sg_indx].size; + offset = 0; + while (tmp_size > 0) { + addr = tmp_sg[sg_indx].pg_map_arr + offset; + if ((!sg_indx && !pg_indx) || !(addr & pmask)) { + pbl->pg_map_arr[pg_indx] = addr &(~pmask); + pbl->pg_count++; + pg_indx++; + } + offset += sginfo->pgsize; + tmp_size -= sginfo->pgsize; + } + } + + vfree(tmp_sg); + return 0; +} + +static int bnxt_qplib_fill_user_dma_pages(struct bnxt_qplib_pbl *pbl, + struct bnxt_qplib_sg_info *sginfo) +{ + int rc = 0; + + rc = __fill_user_dma_pages(pbl, sginfo); + + return rc; +} + +static int __alloc_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl, + struct bnxt_qplib_sg_info *sginfo) +{ + struct pci_dev *pdev; + bool is_umem = false; + int i; + + if (sginfo->nopte) + return 0; + + pdev = res->pdev; + /* page ptr arrays */ + pbl->pg_arr = vmalloc(sginfo->npages * sizeof(void *)); + if (!pbl->pg_arr) + return -ENOMEM; + + pbl->pg_map_arr = vmalloc(sginfo->npages * sizeof(dma_addr_t)); + if (!pbl->pg_map_arr) { + vfree(pbl->pg_arr); + return -ENOMEM; + } + pbl->pg_count = 0; + pbl->pg_size = sginfo->pgsize; + if (!sginfo->sghead) { + for (i = 0; i < sginfo->npages; i++) { + pbl->pg_arr[i] = dma_zalloc_coherent(&pdev->dev, + pbl->pg_size, + &pbl->pg_map_arr[i], + GFP_KERNEL); + if (!pbl->pg_arr[i]) + goto fail; + pbl->pg_count++; + } + } else { + is_umem = true; + if (bnxt_qplib_fill_user_dma_pages(pbl, sginfo)) + goto fail; + } + + return 0; +fail: + __free_pbl(res, pbl, is_umem); + return -ENOMEM; +} + +/* HWQ */ +void bnxt_qplib_free_hwq(struct bnxt_qplib_res *res, + struct bnxt_qplib_hwq *hwq) +{ + int i; + + if (!hwq->max_elements) + return; + if (hwq->level >= PBL_LVL_MAX) + return; + + for (i = 0; i < hwq->level + 1; i++) { + if (i == hwq->level) + __free_pbl(res, &hwq->pbl[i], hwq->is_user); + else + __free_pbl(res, &hwq->pbl[i], false); + } + + hwq->level = PBL_LVL_MAX; + hwq->max_elements = 0; + hwq->element_size = 0; + hwq->prod = hwq->cons = 0; + hwq->cp_bit = 0; +} + +/* All HWQs are power of 2 in size */ +int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, + struct bnxt_qplib_hwq_attr *hwq_attr) +{ + u32 npages = 0, depth, stride, aux_pages = 0; + dma_addr_t *src_phys_ptr, **dst_virt_ptr; + struct bnxt_qplib_sg_info sginfo = {}; + u32 aux_size = 0, npbl, npde; + void *umem; + struct bnxt_qplib_res *res; + u32 aux_slots, pg_size; + struct pci_dev *pdev; + int i, rc, lvl; + + res = hwq_attr->res; + pdev = res->pdev; + umem = hwq_attr->sginfo->sghead; + pg_size = hwq_attr->sginfo->pgsize; + hwq->level = PBL_LVL_MAX; + + depth = roundup_pow_of_two(hwq_attr->depth); + stride = roundup_pow_of_two(hwq_attr->stride); + if (hwq_attr->aux_depth) { + aux_slots = hwq_attr->aux_depth; + aux_size = roundup_pow_of_two(hwq_attr->aux_stride); + aux_pages = (aux_slots * aux_size) / pg_size; + if ((aux_slots * aux_size) % pg_size) + aux_pages++; + } + + if (!umem) { + hwq->is_user = false; + npages = (depth * stride) / pg_size + aux_pages; + if ((depth * stride) % pg_size) + npages++; + if (!npages) + return -EINVAL; + hwq_attr->sginfo->npages = npages; + } else { + hwq->is_user = true; + npages = hwq_attr->sginfo->npages; + npages = (npages * (u64)pg_size) / + BIT_ULL(hwq_attr->sginfo->pgshft); + if ((hwq_attr->sginfo->npages * (u64)pg_size) % + BIT_ULL(hwq_attr->sginfo->pgshft)) + npages++; + } + if (npages == MAX_PBL_LVL_0_PGS && !hwq_attr->sginfo->nopte) { + /* This request is Level 0, map PTE */ + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], hwq_attr->sginfo); + if (rc) + goto fail; + hwq->level = PBL_LVL_0; + goto done; + } + + if (npages >= MAX_PBL_LVL_0_PGS) { + if (npages > MAX_PBL_LVL_1_PGS) { + u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ? + 0 : PTU_PTE_VALID; + /* 2 levels of indirection */ + npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT; + if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT)) + npbl++; + npde = npbl >> MAX_PDL_LVL_SHIFT; + if(npbl % BIT(MAX_PDL_LVL_SHIFT)) + npde++; + /* Alloc PDE pages */ + sginfo.pgsize = npde * PAGE_SIZE; + sginfo.npages = 1; + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo); + + /* Alloc PBL pages */ + sginfo.npages = npbl; + sginfo.pgsize = PAGE_SIZE; + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo); + if (rc) + goto fail; + /* Fill PDL with PBL page pointers */ + dst_virt_ptr = + (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr; + src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr; + if (hwq_attr->type == HWQ_TYPE_MR) { + /* For MR it is expected that we supply only 1 contigous + * page i.e only 1 entry in the PDL that will contain + * all the PBLs for the user supplied memory region + */ + for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++) + dst_virt_ptr[0][i] = src_phys_ptr[i] | + flag; + } else { + for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++) + dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = + src_phys_ptr[i] | PTU_PDE_VALID; + } + /* Alloc or init PTEs */ + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_2], + hwq_attr->sginfo); + if (rc) + goto fail; + hwq->level = PBL_LVL_2; + if (hwq_attr->sginfo->nopte) + goto done; + /* Fill PBLs with PTE pointers */ + dst_virt_ptr = + (dma_addr_t **)hwq->pbl[PBL_LVL_1].pg_arr; + src_phys_ptr = hwq->pbl[PBL_LVL_2].pg_map_arr; + for (i = 0; i < hwq->pbl[PBL_LVL_2].pg_count; i++) { + dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = + src_phys_ptr[i] | PTU_PTE_VALID; + } + if (hwq_attr->type == HWQ_TYPE_QUEUE) { + /* Find the last pg of the size */ + i = hwq->pbl[PBL_LVL_2].pg_count; + dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |= + PTU_PTE_LAST; + if (i > 1) + dst_virt_ptr[PTR_PG(i - 2)] + [PTR_IDX(i - 2)] |= + PTU_PTE_NEXT_TO_LAST; + } + } else { /* pages < 512 npbl = 1, npde = 0 */ + u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ? + 0 : PTU_PTE_VALID; + + /* 1 level of indirection */ + npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT; + if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT)) + npbl++; + sginfo.npages = npbl; + sginfo.pgsize = PAGE_SIZE; + /* Alloc PBL page */ + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo); + if (rc) + goto fail; + /* Alloc or init PTEs */ + rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], + hwq_attr->sginfo); + if (rc) + goto fail; + hwq->level = PBL_LVL_1; + if (hwq_attr->sginfo->nopte) + goto done; + /* Fill PBL with PTE pointers */ + dst_virt_ptr = + (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr; + src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr; + for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++) + dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] = + src_phys_ptr[i] | flag; + if (hwq_attr->type == HWQ_TYPE_QUEUE) { + /* Find the last pg of the size */ + i = hwq->pbl[PBL_LVL_1].pg_count; + dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |= + PTU_PTE_LAST; + if (i > 1) + dst_virt_ptr[PTR_PG(i - 2)] + [PTR_IDX(i - 2)] |= + PTU_PTE_NEXT_TO_LAST; + } + } + } +done: + hwq->prod = 0; + hwq->cons = 0; + hwq->pdev = pdev; + hwq->depth = hwq_attr->depth; + hwq->max_elements = depth; + hwq->element_size = stride; + hwq->qe_ppg = (pg_size/stride); + + if (hwq->level >= PBL_LVL_MAX) + goto fail; + /* For direct access to the elements */ + lvl = hwq->level; + if (hwq_attr->sginfo->nopte && hwq->level) + lvl = hwq->level - 1; + hwq->pbl_ptr = hwq->pbl[lvl].pg_arr; + hwq->pbl_dma_ptr = hwq->pbl[lvl].pg_map_arr; + spin_lock_init(&hwq->lock); + + return 0; +fail: + bnxt_qplib_free_hwq(res, hwq); + return -ENOMEM; +} + +/* Context Tables */ +void bnxt_qplib_free_hwctx(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_ctx *hctx; + int i; + + hctx = res->hctx; + bnxt_qplib_free_hwq(res, &hctx->qp_ctx.hwq); + bnxt_qplib_free_hwq(res, &hctx->mrw_ctx.hwq); + bnxt_qplib_free_hwq(res, &hctx->srq_ctx.hwq); + bnxt_qplib_free_hwq(res, &hctx->cq_ctx.hwq); + bnxt_qplib_free_hwq(res, &hctx->tim_ctx.hwq); + for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) + bnxt_qplib_free_hwq(res, &hctx->tqm_ctx.qtbl[i]); + /* restor original pde level before destroy */ + hctx->tqm_ctx.pde.level = hctx->tqm_ctx.pde_level; + bnxt_qplib_free_hwq(res, &hctx->tqm_ctx.pde); +} + +static int bnxt_qplib_alloc_tqm_rings(struct bnxt_qplib_res *res, + struct bnxt_qplib_ctx *hctx) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_sg_info sginfo = {}; + struct bnxt_qplib_tqm_ctx *tqmctx; + int rc = 0; + int i; + + tqmctx = &hctx->tqm_ctx; + + sginfo.pgsize = PAGE_SIZE; + sginfo.pgshft = PAGE_SHIFT; + hwq_attr.sginfo = &sginfo; + hwq_attr.res = res; + hwq_attr.type = HWQ_TYPE_CTX; + hwq_attr.depth = 512; + hwq_attr.stride = sizeof(u64); + /* Alloc pdl buffer */ + rc = bnxt_qplib_alloc_init_hwq(&tqmctx->pde, &hwq_attr); + if (rc) + goto out; + /* Save original pdl level */ + tqmctx->pde_level = tqmctx->pde.level; + + hwq_attr.stride = 1; + for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) { + if (!tqmctx->qcount[i]) + continue; + hwq_attr.depth = hctx->qp_ctx.max * tqmctx->qcount[i]; + rc = bnxt_qplib_alloc_init_hwq(&tqmctx->qtbl[i], &hwq_attr); + if (rc) + goto out; + } +out: + return rc; +} + +static void bnxt_qplib_map_tqm_pgtbl(struct bnxt_qplib_tqm_ctx *ctx) +{ + struct bnxt_qplib_hwq *qtbl_hwq; + dma_addr_t *dma_ptr; + __le64 **pbl_ptr, *ptr; + int i, j, k; + int fnz_idx = -1; + int pg_count; + + pbl_ptr = (__le64 **)ctx->pde.pbl_ptr; + + for (i = 0, j = 0; i < MAX_TQM_ALLOC_REQ; + i++, j += MAX_TQM_ALLOC_BLK_SIZE) { + qtbl_hwq = &ctx->qtbl[i]; + if (!qtbl_hwq->max_elements) + continue; + if (fnz_idx == -1) + fnz_idx = i; /* first non-zero index */ + switch (qtbl_hwq->level) { + case PBL_LVL_2: + pg_count = qtbl_hwq->pbl[PBL_LVL_1].pg_count; + for (k = 0; k < pg_count; k++) { + ptr = &pbl_ptr[PTR_PG(j + k)][PTR_IDX(j + k)]; + dma_ptr = &qtbl_hwq->pbl[PBL_LVL_1].pg_map_arr[k]; + *ptr = cpu_to_le64(*dma_ptr | PTU_PTE_VALID); + } + break; + case PBL_LVL_1: + case PBL_LVL_0: + default: + ptr = &pbl_ptr[PTR_PG(j)][PTR_IDX(j)]; + *ptr = cpu_to_le64(qtbl_hwq->pbl[PBL_LVL_0].pg_map_arr[0] | + PTU_PTE_VALID); + break; + } + } + if (fnz_idx == -1) + fnz_idx = 0; + /* update pde level as per page table programming */ + ctx->pde.level = (ctx->qtbl[fnz_idx].level == PBL_LVL_2) ? PBL_LVL_2 : + ctx->qtbl[fnz_idx].level + 1; +} + +static int bnxt_qplib_setup_tqm_rings(struct bnxt_qplib_res *res, + struct bnxt_qplib_ctx *hctx) +{ + int rc = 0; + + rc = bnxt_qplib_alloc_tqm_rings(res, hctx); + if (rc) + goto fail; + + bnxt_qplib_map_tqm_pgtbl(&hctx->tqm_ctx); +fail: + return rc; +} + +/* + * Routine: bnxt_qplib_alloc_hwctx + * Description: + * Context tables are memories which are used by the chip. + * The 6 tables defined are: + * QPC ctx - holds QP states + * MRW ctx - holds memory region and window + * SRQ ctx - holds shared RQ states + * CQ ctx - holds completion queue states + * TQM ctx - holds Tx Queue Manager context + * TIM ctx - holds timer context + * Depending on the size of the tbl requested, either a 1 Page Buffer List + * or a 1-to-2-stage indirection Page Directory List + 1 PBL is used + * instead. + * Table might be employed as follows: + * For 0 < ctx size <= 1 PAGE, 0 level of ind is used + * For 1 PAGE < ctx size <= 512 entries size, 1 level of ind is used + * For 512 < ctx size <= MAX, 2 levels of ind is used + * Returns: + * 0 if success, else -ERRORS + */ +int bnxt_qplib_alloc_hwctx(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_sg_info sginfo = {}; + struct bnxt_qplib_ctx *hctx; + struct bnxt_qplib_hwq *hwq; + int rc = 0; + + hctx = res->hctx; + /* QPC Tables */ + sginfo.pgsize = PAGE_SIZE; + sginfo.pgshft = PAGE_SHIFT; + hwq_attr.sginfo = &sginfo; + + hwq_attr.res = res; + hwq_attr.depth = hctx->qp_ctx.max; + hwq_attr.stride = BNXT_QPLIB_MAX_QP_CTX_ENTRY_SIZE; + hwq_attr.type = HWQ_TYPE_CTX; + hwq = &hctx->qp_ctx.hwq; + rc = bnxt_qplib_alloc_init_hwq(hwq, &hwq_attr); + if (rc) + goto fail; + + /* MRW Tables */ + hwq_attr.depth = hctx->mrw_ctx.max; + hwq_attr.stride = BNXT_QPLIB_MAX_MRW_CTX_ENTRY_SIZE; + hwq = &hctx->mrw_ctx.hwq; + rc = bnxt_qplib_alloc_init_hwq(hwq, &hwq_attr); + if (rc) + goto fail; + + /* SRQ Tables */ + hwq_attr.depth = hctx->srq_ctx.max; + hwq_attr.stride = BNXT_QPLIB_MAX_SRQ_CTX_ENTRY_SIZE; + hwq = &hctx->srq_ctx.hwq; + rc = bnxt_qplib_alloc_init_hwq(hwq, &hwq_attr); + if (rc) + goto fail; + + /* CQ Tables */ + hwq_attr.depth = hctx->cq_ctx.max; + hwq_attr.stride = BNXT_QPLIB_MAX_CQ_CTX_ENTRY_SIZE; + hwq = &hctx->cq_ctx.hwq; + rc = bnxt_qplib_alloc_init_hwq(hwq, &hwq_attr); + if (rc) + goto fail; + + /* TQM Buffer */ + rc = bnxt_qplib_setup_tqm_rings(res, hctx); + if (rc) + goto fail; + /* TIM Buffer */ + hwq_attr.depth = hctx->qp_ctx.max * 16; + hwq_attr.stride = 1; + hwq = &hctx->tim_ctx.hwq; + rc = bnxt_qplib_alloc_init_hwq(hwq, &hwq_attr); + if (rc) + goto fail; + + return 0; +fail: + bnxt_qplib_free_hwctx(res); + return rc; +} + +/* GUID */ +void bnxt_qplib_get_guid(const u8 *dev_addr, u8 *guid) +{ + u8 mac[ETH_ALEN]; + + /* MAC-48 to EUI-64 mapping */ + memcpy(mac, dev_addr, ETH_ALEN); + guid[0] = mac[0] ^ 2; + guid[1] = mac[1]; + guid[2] = mac[2]; + guid[3] = 0xff; + guid[4] = 0xfe; + guid[5] = mac[3]; + guid[6] = mac[4]; + guid[7] = mac[5]; +} + +static void bnxt_qplib_free_sgid_tbl(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_sgid_tbl *sgid_tbl; + + sgid_tbl = &res->sgid_tbl; + + if (sgid_tbl->tbl) { + kfree(sgid_tbl->tbl); + sgid_tbl->tbl = NULL; + kfree(sgid_tbl->hw_id); + sgid_tbl->hw_id = NULL; + kfree(sgid_tbl->ctx); + sgid_tbl->ctx = NULL; + kfree(sgid_tbl->vlan); + sgid_tbl->vlan = NULL; + } else { + dev_dbg(&res->pdev->dev, "QPLIB: SGID tbl not present"); + } + sgid_tbl->max = 0; + sgid_tbl->active = 0; +} + +static void bnxt_qplib_free_reftbls(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_reftbl *tbl; + + tbl = &res->reftbl.srqref; + vfree(tbl->rec); + + tbl = &res->reftbl.cqref; + vfree(tbl->rec); + + tbl = &res->reftbl.qpref; + vfree(tbl->rec); +} + +static int bnxt_qplib_alloc_reftbl(struct bnxt_qplib_reftbl *tbl, u32 max) +{ + tbl->max = max; + tbl->rec = vzalloc(sizeof(*tbl->rec) * max); + if (!tbl->rec) + return -ENOMEM; + spin_lock_init(&tbl->lock); + return 0; +} + +static int bnxt_qplib_alloc_reftbls(struct bnxt_qplib_res *res, + struct bnxt_qplib_dev_attr *dattr) +{ + u32 max_cq = BNXT_QPLIB_MAX_CQ_COUNT; + struct bnxt_qplib_reftbl *tbl; + u32 res_cnt; + int rc; + + /* + * Allocating one extra entry to hold QP1 info. + * Store QP1 info at the last entry of the table. + * Decrement the tbl->max by one so that modulo + * operation to get the qp table index from qp id + * returns any value between 0 and max_qp-1 + */ + res_cnt = max_t(u32, BNXT_QPLIB_MAX_QPC_COUNT + 1, dattr->max_qp); + tbl = &res->reftbl.qpref; + rc = bnxt_qplib_alloc_reftbl(tbl, res_cnt); + if (rc) + goto fail; + tbl->max--; + + if (_is_chip_gen_p5_p7(res->cctx)) + max_cq = BNXT_QPLIB_MAX_CQ_COUNT_P5; + res_cnt = max_t(u32, max_cq, dattr->max_cq); + tbl = &res->reftbl.cqref; + rc = bnxt_qplib_alloc_reftbl(tbl, res_cnt); + if (rc) + goto fail; + + res_cnt = max_t(u32, BNXT_QPLIB_MAX_SRQC_COUNT, dattr->max_cq); + tbl = &res->reftbl.srqref; + rc = bnxt_qplib_alloc_reftbl(tbl, BNXT_QPLIB_MAX_SRQC_COUNT); + if (rc) + goto fail; + + return 0; +fail: + return rc; +} + +static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res, u16 max) +{ + struct bnxt_qplib_sgid_tbl *sgid_tbl; + + sgid_tbl = &res->sgid_tbl; + + sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL); + if (!sgid_tbl->tbl) + return -ENOMEM; + + sgid_tbl->hw_id = kcalloc(max, sizeof(u32), GFP_KERNEL); + if (!sgid_tbl->hw_id) + goto free_tbl; + + sgid_tbl->ctx = kcalloc(max, sizeof(void *), GFP_KERNEL); + if (!sgid_tbl->ctx) + goto free_hw_id; + + sgid_tbl->vlan = kcalloc(max, sizeof(u8), GFP_KERNEL); + if (!sgid_tbl->vlan) + goto free_ctx; + + sgid_tbl->max = max; + return 0; +free_ctx: + kfree(sgid_tbl->ctx); +free_hw_id: + kfree(sgid_tbl->hw_id); +free_tbl: + kfree(sgid_tbl->tbl); + return -ENOMEM; +}; + +static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res, + struct bnxt_qplib_sgid_tbl *sgid_tbl) +{ + int i; + + for (i = 0; i < sgid_tbl->max; i++) { + if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, + sizeof(bnxt_qplib_gid_zero))) + bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid, + sgid_tbl->tbl[i].vlan_id, true); + } + memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max); + memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); + memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max); + sgid_tbl->active = 0; +} + +static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl, + struct ifnet *netdev) +{ + u32 i; + + for (i = 0; i < sgid_tbl->max; i++) + sgid_tbl->tbl[i].vlan_id = 0xffff; + memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max); +} + +/* PDs */ +int bnxt_qplib_alloc_pd(struct bnxt_qplib_res *res, struct bnxt_qplib_pd *pd) +{ + u32 bit_num; + int rc = 0; + struct bnxt_qplib_pd_tbl *pdt = &res->pd_tbl; + + mutex_lock(&res->pd_tbl_lock); + bit_num = find_first_bit(pdt->tbl, pdt->max); + if (bit_num == pdt->max - 1) {/* Last bit is reserved */ + rc = -ENOMEM; + goto fail; + } + + /* Found unused PD */ + clear_bit(bit_num, pdt->tbl); + pd->id = bit_num; +fail: + mutex_unlock(&res->pd_tbl_lock); + return rc; +} + +int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res, + struct bnxt_qplib_pd_tbl *pdt, + struct bnxt_qplib_pd *pd) +{ + mutex_lock(&res->pd_tbl_lock); + if (test_and_set_bit(pd->id, pdt->tbl)) { + dev_warn(&res->pdev->dev, "Freeing an unused PD? pdn = %d\n", + pd->id); + mutex_unlock(&res->pd_tbl_lock); + return -EINVAL; + } + /* Reset to reserved pdid. */ + pd->id = pdt->max - 1; + + mutex_unlock(&res->pd_tbl_lock); + return 0; +} + +static void bnxt_qplib_free_pd_tbl(struct bnxt_qplib_pd_tbl *pdt) +{ + if (pdt->tbl) { + kfree(pdt->tbl); + pdt->tbl = NULL; + } + pdt->max = 0; +} + +static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res, u32 max) +{ + struct bnxt_qplib_pd_tbl *pdt; + u32 bytes; + + pdt = &res->pd_tbl; + + max++; /* One extra for reserved pdid. */ + bytes = DIV_ROUND_UP(max, 8); + + if (!bytes) + bytes = 1; + pdt->tbl = kmalloc(bytes, GFP_KERNEL); + if (!pdt->tbl) { + dev_err(&res->pdev->dev, + "QPLIB: PD tbl allocation failed for size = %d\n", bytes); + return -ENOMEM; + } + pdt->max = max; + memset((u8 *)pdt->tbl, 0xFF, bytes); + mutex_init(&res->pd_tbl_lock); + + return 0; +} + +/* DPIs */ +int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi, + void *app, u8 type) +{ + struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; + struct bnxt_qplib_reg_desc *reg; + u32 bit_num; + u64 umaddr; + int rc = 0; + + reg = &dpit->wcreg; + mutex_lock(&res->dpi_tbl_lock); + if (type == BNXT_QPLIB_DPI_TYPE_WC && _is_chip_p7(res->cctx) && + !dpit->avail_ppp) { + rc = -ENOMEM; + goto fail; + } + bit_num = find_first_bit(dpit->tbl, dpit->max); + if (bit_num == dpit->max) { + rc = -ENOMEM; + goto fail; + } + /* Found unused DPI */ + clear_bit(bit_num, dpit->tbl); + dpit->app_tbl[bit_num] = app; + dpi->bit = bit_num; + dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE; + + umaddr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE; + dpi->umdbr = umaddr; + switch (type) { + case BNXT_QPLIB_DPI_TYPE_KERNEL: + /* priviledged dbr was already mapped just initialize it. */ + dpi->umdbr = dpit->ucreg.bar_base + + dpit->ucreg.offset + bit_num * PAGE_SIZE; + dpi->dbr = dpit->priv_db; + dpi->dpi = dpi->bit; + break; + case BNXT_QPLIB_DPI_TYPE_WC: + dpi->dbr = ioremap_wc(umaddr, PAGE_SIZE); + if (_is_chip_p7(res->cctx) && dpi->dbr) + dpit->avail_ppp--; + break; + default: + dpi->dbr = ioremap(umaddr, PAGE_SIZE); + } + if (!dpi->dbr) { + dev_err(&res->pdev->dev, "QPLIB: DB remap failed, type = %d\n", + type); + rc = -ENOMEM; + } + dpi->type = type; +fail: + mutex_unlock(&res->dpi_tbl_lock); + return rc; +} + +int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi) +{ + struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; + int rc = 0; + + mutex_lock(&res->dpi_tbl_lock); + if (dpi->bit >= dpit->max) { + dev_warn(&res->pdev->dev, + "Invalid DPI? dpi = %d, bit = %d\n", + dpi->dpi, dpi->bit); + rc = -EINVAL; + goto fail; + } + + if (dpi->dpi && dpi->type != BNXT_QPLIB_DPI_TYPE_KERNEL) { + if (dpi->type == BNXT_QPLIB_DPI_TYPE_WC && + _is_chip_p7(res->cctx) && dpi->dbr) + dpit->avail_ppp++; + pci_iounmap(res->pdev, dpi->dbr); + } + + if (test_and_set_bit(dpi->bit, dpit->tbl)) { + dev_warn(&res->pdev->dev, + "Freeing an unused DPI? dpi = %d, bit = %d\n", + dpi->dpi, dpi->bit); + rc = -EINVAL; + goto fail; + } + if (dpit->app_tbl) + dpit->app_tbl[dpi->bit] = NULL; + memset(dpi, 0, sizeof(*dpi)); +fail: + mutex_unlock(&res->dpi_tbl_lock); + return rc; +} + +static void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_dpi_tbl *dpit) +{ + kfree(dpit->tbl); + kfree(dpit->app_tbl); + dpit->tbl = NULL; + dpit->app_tbl = NULL; + dpit->max = 0; +} + +static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, + struct bnxt_qplib_dev_attr *dev_attr, + u8 pppp_factor) +{ + struct bnxt_qplib_dpi_tbl *dpit; + struct bnxt_qplib_reg_desc *reg; + unsigned long bar_len; + u32 dbr_offset; + u32 bytes; + + dpit = &res->dpi_tbl; + reg = &dpit->wcreg; + + if (!_is_chip_gen_p5_p7(res->cctx)) { + /* Offest should come from L2 driver */ + dbr_offset = dev_attr->l2_db_size; + dpit->ucreg.offset = dbr_offset; + dpit->wcreg.offset = dbr_offset; + } + + bar_len = pci_resource_len(res->pdev, reg->bar_id); + dpit->max = (bar_len - reg->offset) / PAGE_SIZE; + if (dev_attr->max_dpi) + dpit->max = min_t(u32, dpit->max, dev_attr->max_dpi); + + dpit->app_tbl = kzalloc(dpit->max * sizeof(void*), GFP_KERNEL); + if (!dpit->app_tbl) { + dev_err(&res->pdev->dev, + "QPLIB: DPI app tbl allocation failed"); + return -ENOMEM; + } + + bytes = dpit->max >> 3; + if (!bytes) + bytes = 1; + + dpit->tbl = kmalloc(bytes, GFP_KERNEL); + if (!dpit->tbl) { + kfree(dpit->app_tbl); + dev_err(&res->pdev->dev, + "QPLIB: DPI tbl allocation failed for size = %d\n", + bytes); + return -ENOMEM; + } + + memset((u8 *)dpit->tbl, 0xFF, bytes); + /* + * On SR2, 2nd doorbell page of each function + * is reserved for L2 PPP. Now that the tbl is + * initialized, mark it as unavailable. By default + * RoCE can make use of the 512 extended pages for + * PPP. + */ + if (_is_chip_p7(res->cctx)) { + clear_bit(1, dpit->tbl); + if (pppp_factor) + dpit->avail_ppp = + BNXT_QPLIB_MAX_EXTENDED_PPP_PAGES / pppp_factor; + } + mutex_init(&res->dpi_tbl_lock); + dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; + + return 0; +} + +/* Stats */ +void bnxt_qplib_free_stat_mem(struct bnxt_qplib_res *res, + struct bnxt_qplib_stats *stats) +{ + struct pci_dev *pdev; + + pdev = res->pdev; + if (stats->dma) + dma_free_coherent(&pdev->dev, stats->size, + stats->dma, stats->dma_map); + + memset(stats, 0, sizeof(*stats)); + stats->fw_id = -1; +} + +int bnxt_qplib_alloc_stat_mem(struct pci_dev *pdev, + struct bnxt_qplib_chip_ctx *cctx, + struct bnxt_qplib_stats *stats) +{ + cctx->hw_stats_size = 168; + + memset(stats, 0, sizeof(*stats)); + stats->fw_id = -1; + stats->size = cctx->hw_stats_size; + stats->dma = dma_alloc_coherent(&pdev->dev, stats->size, + &stats->dma_map, GFP_KERNEL); + if (!stats->dma) { + dev_err(&pdev->dev, "QPLIB: Stats DMA allocation failed"); + return -ENOMEM; + } + return 0; +} + +/* Resource */ +int bnxt_qplib_stop_res(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_stop_func_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_stop_func req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_STOP_FUNC, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + return rc; +} + +void bnxt_qplib_clear_tbls(struct bnxt_qplib_res *res) +{ + bnxt_qplib_cleanup_sgid_tbl(res, &res->sgid_tbl); +} + +int bnxt_qplib_init_tbls(struct bnxt_qplib_res *res) +{ + bnxt_qplib_init_sgid_tbl(&res->sgid_tbl, res->netdev); + + return 0; +} + +void bnxt_qplib_free_tbls(struct bnxt_qplib_res *res) +{ + bnxt_qplib_free_sgid_tbl(res); + bnxt_qplib_free_pd_tbl(&res->pd_tbl); + bnxt_qplib_free_dpi_tbl(&res->dpi_tbl); + bnxt_qplib_free_reftbls(res); +} + +int bnxt_qplib_alloc_tbls(struct bnxt_qplib_res *res, u8 pppp_factor) +{ + struct bnxt_qplib_dev_attr *dev_attr; + int rc = 0; + + dev_attr = res->dattr; + + rc = bnxt_qplib_alloc_reftbls(res, dev_attr); + if (rc) + goto fail; + + rc = bnxt_qplib_alloc_sgid_tbl(res, dev_attr->max_sgid); + if (rc) + goto fail; + + rc = bnxt_qplib_alloc_pd_tbl(res, dev_attr->max_pd); + if (rc) + goto fail; + + rc = bnxt_qplib_alloc_dpi_tbl(res, dev_attr, pppp_factor); + if (rc) + goto fail; + + return 0; +fail: + bnxt_qplib_free_tbls(res); + return rc; +} + +void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_reg_desc *reg; + + reg = &res->dpi_tbl.ucreg; + if (reg->bar_reg) + pci_iounmap(res->pdev, reg->bar_reg); + reg->bar_reg = NULL; + reg->bar_base = 0; + reg->len = 0; + reg->bar_id = 0; /* Zero? or ff */ +} + +int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_reg_desc *ucreg; + struct bnxt_qplib_reg_desc *wcreg; + + wcreg = &res->dpi_tbl.wcreg; + wcreg->bar_id = RCFW_DBR_PCI_BAR_REGION; + if (!res || !res->pdev || !wcreg) + return -1; + wcreg->bar_base = pci_resource_start(res->pdev, wcreg->bar_id); + /* No need to set the wcreg->len here */ + + ucreg = &res->dpi_tbl.ucreg; + ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION; + ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id); + + ucreg->offset = 65536; + + ucreg->len = ucreg->offset + PAGE_SIZE; + + if (!ucreg->len || ((ucreg->len & (PAGE_SIZE - 1)) != 0)) { + dev_err(&res->pdev->dev, "QPLIB: invalid dbr length %d\n", + (int)ucreg->len); + return -EINVAL; + } + ucreg->bar_reg = ioremap(ucreg->bar_base, ucreg->len); + if (!ucreg->bar_reg) { + dev_err(&res->pdev->dev, "priviledged dpi map failed!\n"); + return -ENOMEM; + } + + return 0; +} + +/** + * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port + * @dev: the PCI device + * @cap_mask: mask of desired AtomicOp sizes, including one or more of: + * PCI_EXP_DEVCAP2_ATOMIC_COMP32 + * PCI_EXP_DEVCAP2_ATOMIC_COMP64 + * PCI_EXP_DEVCAP2_ATOMIC_COMP128 + * + * Return 0 if all upstream bridges support AtomicOp routing, egress + * blocking is disabled on all upstream ports, and the root port supports + * the requested completion capabilities (32-bit, 64-bit and/or 128-bit + * AtomicOp completion), or negative otherwise. + */ +int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) +{ + struct pci_bus *bus = dev->bus; + struct pci_dev *bridge; + u32 cap; + + if (!pci_is_pcie(dev)) + return -EINVAL; + + /* + * Per PCIe r4.0, sec 6.15, endpoints and root ports may be + * AtomicOp requesters. For now, we only support endpoints as + * requesters and root ports as completers. No endpoints as + * completers, and no peer-to-peer. + */ + + switch (pci_pcie_type(dev)) { + case PCI_EXP_TYPE_ENDPOINT: + case PCI_EXP_TYPE_LEG_END: + break; + default: + return -EINVAL; + } + + bridge = bus->self; + + pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); + + switch (pci_pcie_type(bridge)) { + case PCI_EXP_TYPE_DOWNSTREAM: + if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) + return -EINVAL; + break; + + /* Ensure root port supports all the sizes we care about */ + case PCI_EXP_TYPE_ROOT_PORT: + if ((cap & cap_mask) != cap_mask) + return -EINVAL; + break; + } + return 0; +} + +int bnxt_qplib_enable_atomic_ops_to_root(struct pci_dev *dev) +{ + u16 ctl2; + + if(pci_enable_atomic_ops_to_root(dev, PCI_EXP_DEVCAP2_ATOMIC_COMP32) && + pci_enable_atomic_ops_to_root(dev, PCI_EXP_DEVCAP2_ATOMIC_COMP64)) + return -EOPNOTSUPP; + + pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctl2); + return !(ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ); +} diff --git a/sys/dev/bnxt/bnxt_re/qplib_res.h b/sys/dev/bnxt/bnxt_re/qplib_res.h new file mode 100644 index 000000000000..6468207a49aa --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_res.h @@ -0,0 +1,840 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: QPLib resource manager (header) + */ + +#ifndef __BNXT_QPLIB_RES_H__ +#define __BNXT_QPLIB_RES_H__ + +#include "hsi_struct_def.h" + +extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero; + +#define CHIP_NUM_57508 0x1750 +#define CHIP_NUM_57504 0x1751 +#define CHIP_NUM_57502 0x1752 +#define CHIP_NUM_58818 0xd818 +#define CHIP_NUM_57608 0x1760 + +#define BNXT_QPLIB_MAX_QPC_COUNT (64 * 1024) +#define BNXT_QPLIB_MAX_SRQC_COUNT (64 * 1024) +#define BNXT_QPLIB_MAX_CQ_COUNT (64 * 1024) +#define BNXT_QPLIB_MAX_CQ_COUNT_P5 (128 * 1024) + +#define BNXT_QPLIB_DBR_VALID (0x1UL << 26) +#define BNXT_QPLIB_DBR_EPOCH_SHIFT 24 +#define BNXT_QPLIB_DBR_TOGGLE_SHIFT 25 + +#define BNXT_QPLIB_DBR_PF_DB_OFFSET 0x10000 +#define BNXT_QPLIB_DBR_VF_DB_OFFSET 0x4000 + +#define BNXT_QPLIB_DBR_KEY_INVALID -1 + +/* chip gen type */ +#define BNXT_RE_DEFAULT 0xf + +enum bnxt_qplib_wqe_mode { + BNXT_QPLIB_WQE_MODE_STATIC = 0x00, + BNXT_QPLIB_WQE_MODE_VARIABLE = 0x01, + BNXT_QPLIB_WQE_MODE_INVALID = 0x02 +}; + +#define BNXT_RE_PUSH_MODE_NONE 0 +#define BNXT_RE_PUSH_MODE_WCB 1 +#define BNXT_RE_PUSH_MODE_PPP 2 +#define BNXT_RE_PUSH_ENABLED(mode) ((mode) == BNXT_RE_PUSH_MODE_WCB ||\ + (mode) == BNXT_RE_PUSH_MODE_PPP) +#define BNXT_RE_PPP_ENABLED(cctx) ((cctx)->modes.db_push_mode ==\ + BNXT_RE_PUSH_MODE_PPP) +#define PCI_EXP_DEVCAP2_ATOMIC_ROUTE 0x00000040 /* Atomic Op routing */ +#define PCI_EXP_DEVCAP2_ATOMIC_COMP32 0x00000080 /* 32b AtomicOp completion */ +#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 0x00000100 /* 64b AtomicOp completion */ +#define PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */ +#define PCI_EXP_DEVCTL2_ATOMIC_REQ 0x0040 /* Set Atomic requests */ + +int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask); + +struct bnxt_qplib_drv_modes { + u8 wqe_mode; + u8 te_bypass; + u8 db_push; + /* To control advanced cc params display in configfs */ + u8 cc_pr_mode; + /* Other modes to follow here e.g. GSI QP mode */ + u8 dbr_pacing; + u8 dbr_pacing_ext; + u8 dbr_drop_recov; + u8 dbr_primary_pf; + u8 dbr_pacing_v0; +}; + +struct bnxt_qplib_chip_ctx { + u16 chip_num; + u8 chip_rev; + u8 chip_metal; + u64 hwrm_intf_ver; + struct bnxt_qplib_drv_modes modes; + u32 dbr_stat_db_fifo; + u32 dbr_aeq_arm_reg; + u32 dbr_throttling_reg; + u16 hw_stats_size; + u16 hwrm_cmd_max_timeout; +}; + +static inline bool _is_chip_num_p7(u16 chip_num) +{ + return (chip_num == CHIP_NUM_58818 || + chip_num == CHIP_NUM_57608); +} + +static inline bool _is_chip_p7(struct bnxt_qplib_chip_ctx *cctx) +{ + return _is_chip_num_p7(cctx->chip_num); +} + +/* SR2 is Gen P5 */ +static inline bool _is_chip_gen_p5(struct bnxt_qplib_chip_ctx *cctx) +{ + return (cctx->chip_num == CHIP_NUM_57508 || + cctx->chip_num == CHIP_NUM_57504 || + cctx->chip_num == CHIP_NUM_57502); +} + +static inline bool _is_chip_gen_p5_p7(struct bnxt_qplib_chip_ctx *cctx) +{ + return (_is_chip_gen_p5(cctx) || _is_chip_p7(cctx)); +} + +static inline bool _is_wqe_mode_variable(struct bnxt_qplib_chip_ctx *cctx) +{ + return cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE; +} + +struct bnxt_qplib_db_pacing_data { + u32 do_pacing; + u32 pacing_th; + u32 dev_err_state; + u32 alarm_th; + u32 grc_reg_offset; + u32 fifo_max_depth; + u32 fifo_room_mask; + u8 fifo_room_shift; +}; + +static inline u8 bnxt_qplib_dbr_pacing_en(struct bnxt_qplib_chip_ctx *cctx) +{ + return cctx->modes.dbr_pacing; +} + +static inline u8 bnxt_qplib_dbr_pacing_ext_en(struct bnxt_qplib_chip_ctx *cctx) +{ + return cctx->modes.dbr_pacing_ext; +} + +static inline u8 bnxt_qplib_dbr_pacing_is_primary_pf(struct bnxt_qplib_chip_ctx *cctx) +{ + return cctx->modes.dbr_primary_pf; +} + +static inline void bnxt_qplib_dbr_pacing_set_primary_pf + (struct bnxt_qplib_chip_ctx *cctx, u8 val) +{ + cctx->modes.dbr_primary_pf = val; +} + +/* Defines for handling the HWRM version check */ +#define HWRM_VERSION_DEV_ATTR_MAX_DPI 0x1000A0000000D +#define HWRM_VERSION_ROCE_STATS_FN_ID 0x1000A00000045 + +#define PTR_CNT_PER_PG (PAGE_SIZE / sizeof(void *)) +#define PTR_MAX_IDX_PER_PG (PTR_CNT_PER_PG - 1) +#define PTR_PG(x) (((x) & ~PTR_MAX_IDX_PER_PG) / PTR_CNT_PER_PG) +#define PTR_IDX(x) ((x) & PTR_MAX_IDX_PER_PG) + +#define HWQ_CMP(idx, hwq) ((idx) & ((hwq)->max_elements - 1)) +#define HWQ_FREE_SLOTS(hwq) (hwq->max_elements - \ + ((HWQ_CMP(hwq->prod, hwq)\ + - HWQ_CMP(hwq->cons, hwq))\ + & (hwq->max_elements - 1))) +enum bnxt_qplib_hwq_type { + HWQ_TYPE_CTX, + HWQ_TYPE_QUEUE, + HWQ_TYPE_L2_CMPL, + HWQ_TYPE_MR +}; + +#define MAX_PBL_LVL_0_PGS 1 +#define MAX_PBL_LVL_1_PGS 512 +#define MAX_PBL_LVL_1_PGS_SHIFT 9 +#define MAX_PDL_LVL_SHIFT 9 + +enum bnxt_qplib_pbl_lvl { + PBL_LVL_0, + PBL_LVL_1, + PBL_LVL_2, + PBL_LVL_MAX +}; + +#define ROCE_PG_SIZE_4K (4 * 1024) +#define ROCE_PG_SIZE_8K (8 * 1024) +#define ROCE_PG_SIZE_64K (64 * 1024) +#define ROCE_PG_SIZE_2M (2 * 1024 * 1024) +#define ROCE_PG_SIZE_8M (8 * 1024 * 1024) +#define ROCE_PG_SIZE_1G (1024 * 1024 * 1024) +enum bnxt_qplib_hwrm_pg_size { + BNXT_QPLIB_HWRM_PG_SIZE_4K = 0, + BNXT_QPLIB_HWRM_PG_SIZE_8K = 1, + BNXT_QPLIB_HWRM_PG_SIZE_64K = 2, + BNXT_QPLIB_HWRM_PG_SIZE_2M = 3, + BNXT_QPLIB_HWRM_PG_SIZE_8M = 4, + BNXT_QPLIB_HWRM_PG_SIZE_1G = 5, +}; + +struct bnxt_qplib_reg_desc { + u8 bar_id; + resource_size_t bar_base; + unsigned long offset; + void __iomem *bar_reg; + size_t len; +}; + +struct bnxt_qplib_pbl { + u32 pg_count; + u32 pg_size; + void **pg_arr; + dma_addr_t *pg_map_arr; +}; + +struct bnxt_qplib_sg_info { + struct scatterlist *sghead; + u32 nmap; + u32 npages; + u32 pgshft; + u32 pgsize; + bool nopte; +}; + +struct bnxt_qplib_hwq_attr { + struct bnxt_qplib_res *res; + struct bnxt_qplib_sg_info *sginfo; + enum bnxt_qplib_hwq_type type; + u32 depth; + u32 stride; + u32 aux_stride; + u32 aux_depth; +}; + +struct bnxt_qplib_hwq { + struct pci_dev *pdev; + spinlock_t lock; + struct bnxt_qplib_pbl pbl[PBL_LVL_MAX]; + enum bnxt_qplib_pbl_lvl level; /* 0, 1, or 2 */ + void **pbl_ptr; /* ptr for easy access + to the PBL entries */ + dma_addr_t *pbl_dma_ptr; /* ptr for easy access + to the dma_addr */ + u32 max_elements; + u32 depth; /* original requested depth */ + u16 element_size; /* Size of each entry */ + u16 qe_ppg; /* queue entry per page */ + + u32 prod; /* raw */ + u32 cons; /* raw */ + u8 cp_bit; + u8 is_user; + u64 *pad_pg; + u32 pad_stride; + u32 pad_pgofft; +}; + +struct bnxt_qplib_db_info { + void __iomem *db; + void __iomem *priv_db; + struct bnxt_qplib_hwq *hwq; + struct bnxt_qplib_res *res; + u32 xid; + u32 max_slot; + u32 flags; + u8 toggle; + spinlock_t lock; + u64 shadow_key; + u64 shadow_key_arm_ena; + u32 seed; /* For DB pacing */ +}; + +enum bnxt_qplib_db_info_flags_mask { + BNXT_QPLIB_FLAG_EPOCH_CONS_SHIFT = 0x0UL, + BNXT_QPLIB_FLAG_EPOCH_PROD_SHIFT = 0x1UL, + BNXT_QPLIB_FLAG_EPOCH_CONS_MASK = 0x1UL, + BNXT_QPLIB_FLAG_EPOCH_PROD_MASK = 0x2UL, +}; + +enum bnxt_qplib_db_epoch_flag_shift { + BNXT_QPLIB_DB_EPOCH_CONS_SHIFT = BNXT_QPLIB_DBR_EPOCH_SHIFT, + BNXT_QPLIB_DB_EPOCH_PROD_SHIFT = (BNXT_QPLIB_DBR_EPOCH_SHIFT - 1) +}; + +/* Tables */ +struct bnxt_qplib_pd_tbl { + unsigned long *tbl; + u32 max; +}; + +struct bnxt_qplib_sgid_tbl { + struct bnxt_qplib_gid_info *tbl; + u16 *hw_id; + u16 max; + u16 active; + void *ctx; + bool *vlan; +}; + +enum { + BNXT_QPLIB_DPI_TYPE_KERNEL = 0, + BNXT_QPLIB_DPI_TYPE_UC = 1, + BNXT_QPLIB_DPI_TYPE_WC = 2 +}; + +struct bnxt_qplib_dpi { + u32 dpi; + u32 bit; + void __iomem *dbr; + u64 umdbr; + u8 type; +}; + +#define BNXT_QPLIB_MAX_EXTENDED_PPP_PAGES 512 +struct bnxt_qplib_dpi_tbl { + void **app_tbl; + unsigned long *tbl; + u16 max; + u16 avail_ppp; + struct bnxt_qplib_reg_desc ucreg; /* Hold entire DB bar. */ + struct bnxt_qplib_reg_desc wcreg; + void __iomem *priv_db; +}; + +struct bnxt_qplib_stats { + dma_addr_t dma_map; + void *dma; + u32 size; + u32 fw_id; +}; + +struct bnxt_qplib_vf_res { + u32 max_qp; + u32 max_mrw; + u32 max_srq; + u32 max_cq; + u32 max_gid; +}; + +#define BNXT_QPLIB_MAX_QP_CTX_ENTRY_SIZE 448 +#define BNXT_QPLIB_MAX_SRQ_CTX_ENTRY_SIZE 64 +#define BNXT_QPLIB_MAX_CQ_CTX_ENTRY_SIZE 64 +#define BNXT_QPLIB_MAX_MRW_CTX_ENTRY_SIZE 128 + +#define MAX_TQM_ALLOC_REQ 48 +#define MAX_TQM_ALLOC_BLK_SIZE 8 +struct bnxt_qplib_tqm_ctx { + struct bnxt_qplib_hwq pde; + enum bnxt_qplib_pbl_lvl pde_level; /* Original level */ + struct bnxt_qplib_hwq qtbl[MAX_TQM_ALLOC_REQ]; + u8 qcount[MAX_TQM_ALLOC_REQ]; +}; + +struct bnxt_qplib_hctx { + struct bnxt_qplib_hwq hwq; + u32 max; +}; + +struct bnxt_qplib_refrec { + void *handle; + u32 xid; +}; + +struct bnxt_qplib_reftbl { + struct bnxt_qplib_refrec *rec; + u32 max; + spinlock_t lock; /* reftbl lock */ +}; + +struct bnxt_qplib_reftbls { + struct bnxt_qplib_reftbl qpref; + struct bnxt_qplib_reftbl cqref; + struct bnxt_qplib_reftbl srqref; +}; + +#define GET_TBL_INDEX(id, tbl) ((id) % (((tbl)->max) - 1)) +static inline u32 map_qp_id_to_tbl_indx(u32 qid, struct bnxt_qplib_reftbl *tbl) +{ + return (qid == 1) ? tbl->max : GET_TBL_INDEX(qid, tbl); +} + +/* + * This structure includes the number of various roce resource table sizes + * actually allocated by the driver. May be less than the maximums the firmware + * allows if the driver imposes lower limits than the firmware. + */ +struct bnxt_qplib_ctx { + struct bnxt_qplib_hctx qp_ctx; + struct bnxt_qplib_hctx mrw_ctx; + struct bnxt_qplib_hctx srq_ctx; + struct bnxt_qplib_hctx cq_ctx; + struct bnxt_qplib_hctx tim_ctx; + struct bnxt_qplib_tqm_ctx tqm_ctx; + + struct bnxt_qplib_stats stats; + struct bnxt_qplib_stats stats2; + struct bnxt_qplib_vf_res vf_res; +}; + +struct bnxt_qplib_res { + struct pci_dev *pdev; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_qplib_dev_attr *dattr; + struct bnxt_qplib_ctx *hctx; + struct ifnet *netdev; + struct bnxt_en_dev *en_dev; + + struct bnxt_qplib_rcfw *rcfw; + + struct bnxt_qplib_pd_tbl pd_tbl; + struct mutex pd_tbl_lock; + struct bnxt_qplib_sgid_tbl sgid_tbl; + struct bnxt_qplib_dpi_tbl dpi_tbl; + struct mutex dpi_tbl_lock; + struct bnxt_qplib_reftbls reftbl; + bool prio; + bool is_vf; + struct bnxt_qplib_db_pacing_data *pacing_data; +}; + +struct bnxt_qplib_query_stats_info { + u32 function_id; + u8 collection_id; + bool vf_valid; +}; + +struct bnxt_qplib_query_qp_info { + u32 function_id; + u32 num_qps; + u32 start_index; + bool vf_valid; +}; + +struct bnxt_qplib_query_fn_info { + bool vf_valid; + u32 host; + u32 filter; +}; + + +#define to_bnxt_qplib(ptr, type, member) \ + container_of(ptr, type, member) + +struct bnxt_qplib_pd; +struct bnxt_qplib_dev_attr; + +bool _is_chip_gen_p5(struct bnxt_qplib_chip_ctx *cctx); +bool _is_chip_gen_p5_p7(struct bnxt_qplib_chip_ctx *cctx); +bool _is_chip_a0(struct bnxt_qplib_chip_ctx *cctx); +bool _is_chip_p7(struct bnxt_qplib_chip_ctx *cctx); +bool _is_alloc_mr_unified(struct bnxt_qplib_dev_attr *dattr); +void bnxt_qplib_free_hwq(struct bnxt_qplib_res *res, + struct bnxt_qplib_hwq *hwq); +int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, + struct bnxt_qplib_hwq_attr *hwq_attr); +void bnxt_qplib_get_guid(const u8 *dev_addr, u8 *guid); +int bnxt_qplib_alloc_pd(struct bnxt_qplib_res *res, + struct bnxt_qplib_pd *pd); +int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res, + struct bnxt_qplib_pd_tbl *pd_tbl, + struct bnxt_qplib_pd *pd); +int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi, + void *app, u8 type); +int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi); +int bnxt_qplib_stop_res(struct bnxt_qplib_res *res); +void bnxt_qplib_clear_tbls(struct bnxt_qplib_res *res); +int bnxt_qplib_init_tbls(struct bnxt_qplib_res *res); +void bnxt_qplib_free_tbls(struct bnxt_qplib_res *res); +int bnxt_qplib_alloc_tbls(struct bnxt_qplib_res *res, u8 pppp_factor); +void bnxt_qplib_free_hwctx(struct bnxt_qplib_res *res); +int bnxt_qplib_alloc_hwctx(struct bnxt_qplib_res *res); +int bnxt_qplib_alloc_stat_mem(struct pci_dev *pdev, + struct bnxt_qplib_chip_ctx *cctx, + struct bnxt_qplib_stats *stats); +void bnxt_qplib_free_stat_mem(struct bnxt_qplib_res *res, + struct bnxt_qplib_stats *stats); + +int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res); +void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res); +int bnxt_qplib_enable_atomic_ops_to_root(struct pci_dev *dev); +u8 _get_chip_gen_p5_type(struct bnxt_qplib_chip_ctx *cctx); + +static inline void *bnxt_qplib_get_qe(struct bnxt_qplib_hwq *hwq, + u32 indx, u64 *pg) +{ + u32 pg_num, pg_idx; + + pg_num = (indx / hwq->qe_ppg); + pg_idx = (indx % hwq->qe_ppg); + if (pg) + *pg = (u64)&hwq->pbl_ptr[pg_num]; + return (void *)((u8 *)hwq->pbl_ptr[pg_num] + hwq->element_size * pg_idx); +} + +static inline void bnxt_qplib_hwq_incr_prod(struct bnxt_qplib_db_info *dbinfo, + struct bnxt_qplib_hwq *hwq, u32 cnt) +{ + /* move prod and update toggle/epoch if wrap around */ + hwq->prod += cnt; + if (hwq->prod >= hwq->depth) { + hwq->prod %= hwq->depth; + dbinfo->flags ^= 1UL << BNXT_QPLIB_FLAG_EPOCH_PROD_SHIFT; + } +} + +static inline void bnxt_qplib_hwq_incr_cons(u32 max_elements, u32 *cons, + u32 cnt, u32 *dbinfo_flags) +{ + /* move cons and update toggle/epoch if wrap around */ + *cons += cnt; + if (*cons >= max_elements) { + *cons %= max_elements; + *dbinfo_flags ^= 1UL << BNXT_QPLIB_FLAG_EPOCH_CONS_SHIFT; + } +} + +static inline u8 _get_pte_pg_size(struct bnxt_qplib_hwq *hwq) +{ + u8 pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; + struct bnxt_qplib_pbl *pbl; + + pbl = &hwq->pbl[hwq->level]; + switch (pbl->pg_size) { + case ROCE_PG_SIZE_4K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; + break; + case ROCE_PG_SIZE_8K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8K; + break; + case ROCE_PG_SIZE_64K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_64K; + break; + case ROCE_PG_SIZE_2M: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_2M; + break; + case ROCE_PG_SIZE_8M: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8M; + break; + case ROCE_PG_SIZE_1G: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_1G; + break; + default: + break; + } + return pg_size; +} + +static inline u64 _get_base_addr(struct bnxt_qplib_hwq *hwq) +{ + return hwq->pbl[PBL_LVL_0].pg_map_arr[0]; +} + +static inline u8 _get_base_pg_size(struct bnxt_qplib_hwq *hwq) +{ + u8 pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; + struct bnxt_qplib_pbl *pbl; + + pbl = &hwq->pbl[PBL_LVL_0]; + switch (pbl->pg_size) { + case ROCE_PG_SIZE_4K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; + break; + case ROCE_PG_SIZE_8K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8K; + break; + case ROCE_PG_SIZE_64K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_64K; + break; + case ROCE_PG_SIZE_2M: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_2M; + break; + case ROCE_PG_SIZE_8M: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_8M; + break; + case ROCE_PG_SIZE_1G: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_1G; + break; + default: + break; + } + return pg_size; +} + +static inline enum bnxt_qplib_hwq_type _get_hwq_type(struct bnxt_qplib_res *res) +{ + return _is_chip_gen_p5_p7(res->cctx) ? HWQ_TYPE_QUEUE : HWQ_TYPE_L2_CMPL; +} + +static inline bool _is_ext_stats_supported(u16 dev_cap_flags) +{ + return dev_cap_flags & + CREQ_QUERY_FUNC_RESP_SB_EXT_STATS; +} + +static inline int bnxt_ext_stats_supported(struct bnxt_qplib_chip_ctx *ctx, + u16 flags, bool virtfn) +{ + return (_is_ext_stats_supported(flags) && + ((virtfn && _is_chip_p7(ctx)) || (!virtfn))); +} + +static inline bool _is_hw_retx_supported(u16 dev_cap_flags) +{ + return dev_cap_flags & + (CREQ_QUERY_FUNC_RESP_SB_HW_REQUESTER_RETX_ENABLED | + CREQ_QUERY_FUNC_RESP_SB_HW_RESPONDER_RETX_ENABLED); +} + +/* Disable HW_RETX */ +#define BNXT_RE_HW_RETX(a) _is_hw_retx_supported((a)) + +static inline bool _is_cqe_v2_supported(u16 dev_cap_flags) +{ + return dev_cap_flags & + CREQ_QUERY_FUNC_RESP_SB_CQE_V2; +} + +#define BNXT_DB_FIFO_ROOM_MASK 0x1fff8000 +#define BNXT_DB_FIFO_ROOM_SHIFT 15 +#define BNXT_MAX_FIFO_DEPTH 0x2c00 + +#define BNXT_DB_PACING_ALGO_THRESHOLD 250 +#define BNXT_DEFAULT_PACING_PROBABILITY 0xFFFF + +#define BNXT_DBR_PACING_WIN_BASE 0x2000 +#define BNXT_DBR_PACING_WIN_MAP_OFF 4 +#define BNXT_DBR_PACING_WIN_OFF(reg) (BNXT_DBR_PACING_WIN_BASE + \ + +static inline void bnxt_qplib_ring_db32(struct bnxt_qplib_db_info *info, + bool arm) +{ + u32 key = 0; + + key = info->hwq->cons | (CMPL_DOORBELL_IDX_VALID | + (CMPL_DOORBELL_KEY_CMPL & CMPL_DOORBELL_KEY_MASK)); + if (!arm) + key |= CMPL_DOORBELL_MASK; + /* memory barrier */ + wmb(); + writel(key, info->db); +} + +#define BNXT_QPLIB_INIT_DBHDR(xid, type, indx, toggle) \ + (((u64)(((xid) & DBC_DBC_XID_MASK) | DBC_DBC_PATH_ROCE | \ + (type) | BNXT_QPLIB_DBR_VALID) << 32) | (indx) | \ + ((toggle) << (BNXT_QPLIB_DBR_TOGGLE_SHIFT))) + +static inline void bnxt_qplib_write_db(struct bnxt_qplib_db_info *info, + u64 key, void __iomem *db, + u64 *shadow_key) +{ + unsigned long flags; + + spin_lock_irqsave(&info->lock, flags); + *shadow_key = key; + writeq(key, db); + spin_unlock_irqrestore(&info->lock, flags); +} + +static inline void __replay_writeq(u64 key, void __iomem *db) +{ + /* No need to replay uninitialised shadow_keys */ + if (key != BNXT_QPLIB_DBR_KEY_INVALID) + writeq(key, db); +} + +static inline void bnxt_qplib_replay_db(struct bnxt_qplib_db_info *info, + bool is_arm_ena) + +{ + if (!spin_trylock_irq(&info->lock)) + return; + + if (is_arm_ena) + __replay_writeq(info->shadow_key_arm_ena, info->priv_db); + else + __replay_writeq(info->shadow_key, info->db); + + spin_unlock_irq(&info->lock); +} + +static inline void bnxt_qplib_ring_db(struct bnxt_qplib_db_info *info, + u32 type) +{ + u64 key = 0; + u32 indx; + u8 toggle = 0; + + if (type == DBC_DBC_TYPE_CQ_ARMALL || + type == DBC_DBC_TYPE_CQ_ARMSE) + toggle = info->toggle; + + indx = ((info->hwq->cons & DBC_DBC_INDEX_MASK) | + ((info->flags & BNXT_QPLIB_FLAG_EPOCH_CONS_MASK) << + BNXT_QPLIB_DB_EPOCH_CONS_SHIFT)); + + key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, indx, toggle); + bnxt_qplib_write_db(info, key, info->db, &info->shadow_key); +} + +static inline void bnxt_qplib_ring_prod_db(struct bnxt_qplib_db_info *info, + u32 type) +{ + u64 key = 0; + u32 indx; + + indx = (((info->hwq->prod / info->max_slot) & DBC_DBC_INDEX_MASK) | + ((info->flags & BNXT_QPLIB_FLAG_EPOCH_PROD_MASK) << + BNXT_QPLIB_DB_EPOCH_PROD_SHIFT)); + key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, indx, 0); + bnxt_qplib_write_db(info, key, info->db, &info->shadow_key); +} + +static inline void bnxt_qplib_armen_db(struct bnxt_qplib_db_info *info, + u32 type) +{ + u64 key = 0; + u8 toggle = 0; + + if (type == DBC_DBC_TYPE_CQ_ARMENA) + toggle = info->toggle; + /* Index always at 0 */ + key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, 0, toggle); + bnxt_qplib_write_db(info, key, info->priv_db, + &info->shadow_key_arm_ena); +} + +static inline void bnxt_qplib_cq_coffack_db(struct bnxt_qplib_db_info *info) +{ + u64 key = 0; + + /* Index always at 0 */ + key = BNXT_QPLIB_INIT_DBHDR(info->xid, DBC_DBC_TYPE_CQ_CUTOFF_ACK, 0, 0); + bnxt_qplib_write_db(info, key, info->priv_db, &info->shadow_key); +} + +static inline void bnxt_qplib_srq_arm_db(struct bnxt_qplib_db_info *info) +{ + u64 key = 0; + + /* Index always at 0 */ + key = BNXT_QPLIB_INIT_DBHDR(info->xid, DBC_DBC_TYPE_SRQ_ARM, 0, 0); + bnxt_qplib_write_db(info, key, info->priv_db, &info->shadow_key); +} + +static inline void bnxt_qplib_ring_nq_db(struct bnxt_qplib_db_info *info, + struct bnxt_qplib_chip_ctx *cctx, + bool arm) +{ + u32 type; + + type = arm ? DBC_DBC_TYPE_NQ_ARM : DBC_DBC_TYPE_NQ; + if (_is_chip_gen_p5_p7(cctx)) + bnxt_qplib_ring_db(info, type); + else + bnxt_qplib_ring_db32(info, arm); +} + +struct bnxt_qplib_max_res { + u32 max_qp; + u32 max_mr; + u32 max_cq; + u32 max_srq; + u32 max_ah; + u32 max_pd; +}; + +/* + * Defines for maximum resources supported for chip revisions + * Maximum PDs supported are restricted to Max QPs + * GENP4 - Wh+ + * DEFAULT - Thor + */ +#define BNXT_QPLIB_GENP4_PF_MAX_QP (16 * 1024) +#define BNXT_QPLIB_GENP4_PF_MAX_MRW (16 * 1024) +#define BNXT_QPLIB_GENP4_PF_MAX_CQ (16 * 1024) +#define BNXT_QPLIB_GENP4_PF_MAX_SRQ (1 * 1024) +#define BNXT_QPLIB_GENP4_PF_MAX_AH (16 * 1024) +#define BNXT_QPLIB_GENP4_PF_MAX_PD BNXT_QPLIB_GENP4_PF_MAX_QP + +#define BNXT_QPLIB_DEFAULT_PF_MAX_QP (64 * 1024) +#define BNXT_QPLIB_DEFAULT_PF_MAX_MRW (256 * 1024) +#define BNXT_QPLIB_DEFAULT_PF_MAX_CQ (64 * 1024) +#define BNXT_QPLIB_DEFAULT_PF_MAX_SRQ (4 * 1024) +#define BNXT_QPLIB_DEFAULT_PF_MAX_AH (64 * 1024) +#define BNXT_QPLIB_DEFAULT_PF_MAX_PD BNXT_QPLIB_DEFAULT_PF_MAX_QP + +#define BNXT_QPLIB_DEFAULT_VF_MAX_QP (6 * 1024) +#define BNXT_QPLIB_DEFAULT_VF_MAX_MRW (6 * 1024) +#define BNXT_QPLIB_DEFAULT_VF_MAX_CQ (6 * 1024) +#define BNXT_QPLIB_DEFAULT_VF_MAX_SRQ (4 * 1024) +#define BNXT_QPLIB_DEFAULT_VF_MAX_AH (6 * 1024) +#define BNXT_QPLIB_DEFAULT_VF_MAX_PD BNXT_QPLIB_DEFAULT_VF_MAX_QP + +static inline void bnxt_qplib_max_res_supported(struct bnxt_qplib_chip_ctx *cctx, + struct bnxt_qplib_res *qpl_res, + struct bnxt_qplib_max_res *max_res, + bool vf_res_limit) +{ + switch (cctx->chip_num) { + case CHIP_NUM_57608: + case CHIP_NUM_58818: + case CHIP_NUM_57504: + case CHIP_NUM_57502: + case CHIP_NUM_57508: + if (!qpl_res->is_vf) { + max_res->max_qp = BNXT_QPLIB_DEFAULT_PF_MAX_QP; + max_res->max_mr = BNXT_QPLIB_DEFAULT_PF_MAX_MRW; + max_res->max_cq = BNXT_QPLIB_DEFAULT_PF_MAX_CQ; + max_res->max_srq = BNXT_QPLIB_DEFAULT_PF_MAX_SRQ; + max_res->max_ah = BNXT_QPLIB_DEFAULT_PF_MAX_AH; + max_res->max_pd = BNXT_QPLIB_DEFAULT_PF_MAX_PD; + } else { + max_res->max_qp = BNXT_QPLIB_DEFAULT_VF_MAX_QP; + max_res->max_mr = BNXT_QPLIB_DEFAULT_VF_MAX_MRW; + max_res->max_cq = BNXT_QPLIB_DEFAULT_VF_MAX_CQ; + max_res->max_srq = BNXT_QPLIB_DEFAULT_VF_MAX_SRQ; + max_res->max_ah = BNXT_QPLIB_DEFAULT_VF_MAX_AH; + max_res->max_pd = BNXT_QPLIB_DEFAULT_VF_MAX_PD; + } + break; + default: + /* Wh+/Stratus max resources */ + max_res->max_qp = BNXT_QPLIB_GENP4_PF_MAX_QP; + max_res->max_mr = BNXT_QPLIB_GENP4_PF_MAX_MRW; + max_res->max_cq = BNXT_QPLIB_GENP4_PF_MAX_CQ; + max_res->max_srq = BNXT_QPLIB_GENP4_PF_MAX_SRQ; + max_res->max_ah = BNXT_QPLIB_GENP4_PF_MAX_AH; + max_res->max_pd = BNXT_QPLIB_GENP4_PF_MAX_PD; + break; + } +} +#endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_sp.c b/sys/dev/bnxt/bnxt_re/qplib_sp.c new file mode 100644 index 000000000000..c414718a816f --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_sp.c @@ -0,0 +1,1234 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Slow Path Operators + */ + +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/if_ether.h> +#include <linux/printk.h> + +#include "hsi_struct_def.h" +#include "qplib_tlv.h" +#include "qplib_res.h" +#include "qplib_rcfw.h" +#include "qplib_sp.h" + +const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }}; + +/* Device */ +static u8 bnxt_qplib_is_atomic_cap(struct bnxt_qplib_rcfw *rcfw) +{ + u16 pcie_ctl2 = 0; + + if (!_is_chip_gen_p5_p7(rcfw->res->cctx)) + return false; + pcie_capability_read_word(rcfw->pdev, PCI_EXP_DEVCTL2, &pcie_ctl2); + return (pcie_ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ); +} + +static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, char *fw_ver) +{ + struct creq_query_version_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_query_version req = {}; + int rc = 0; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_VERSION, + sizeof(req)); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) { + dev_err(&rcfw->pdev->dev, "QPLIB: Failed to query version\n"); + return; + } + fw_ver[0] = resp.fw_maj; + fw_ver[1] = resp.fw_minor; + fw_ver[2] = resp.fw_bld; + fw_ver[3] = resp.fw_rsvd; +} + +int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) +{ + struct creq_query_func_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct creq_query_func_resp_sb *sb; + struct bnxt_qplib_rcfw_sbuf sbuf; + struct bnxt_qplib_dev_attr *attr; + struct bnxt_qplib_chip_ctx *cctx; + struct cmdq_query_func req = {}; + u8 *tqm_alloc; + int i, rc = 0; + u32 temp; + u8 chip_gen = BNXT_RE_DEFAULT; + + cctx = rcfw->res->cctx; + attr = rcfw->res->dattr; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_FUNC, + sizeof(req)); + + sbuf.size = sizeof(*sb); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) + return -ENOMEM; + + sb = sbuf.sb; + req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto bail; + /* Extract the context from the side buffer */ + chip_gen = _get_chip_gen_p5_type(cctx); + attr->max_qp = le32_to_cpu(sb->max_qp); + attr->max_qp = min_t(u32, attr->max_qp, BNXT_RE_MAX_QP_SUPPORTED(chip_gen)); + /* max_qp value reported by FW does not include the QP1 */ + attr->max_qp += 1; + attr->max_qp_rd_atom = + sb->max_qp_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? + BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom; + attr->max_qp_init_rd_atom = + sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? + BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; + /* Report 1 less than the max_qp_wqes reported by FW as driver adds + * one extra entry while creating the qp + */ + attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1; + /* Adjust for max_qp_wqes for variable wqe */ + if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) { + attr->max_qp_wqes = (BNXT_MAX_SQ_SIZE) / + (BNXT_MAX_VAR_WQE_SIZE / BNXT_SGE_SIZE) - 1; + } + if (!_is_chip_gen_p5_p7(cctx)) { + /* + * 128 WQEs needs to be reserved for the HW (8916). Prevent + * reporting the max number for gen-p4 only. + */ + attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS; + } + attr->max_qp_sges = sb->max_sge; + if (_is_chip_gen_p5_p7(cctx) && + cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + attr->max_qp_sges = sb->max_sge_var_wqe; + attr->max_cq = le32_to_cpu(sb->max_cq); + attr->max_cq = min_t(u32, attr->max_cq, BNXT_RE_MAX_CQ_SUPPORTED(chip_gen)); + + attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); + attr->max_cq_wqes = min_t(u32, BNXT_QPLIB_MAX_CQ_WQES, attr->max_cq_wqes); + + attr->max_cq_sges = attr->max_qp_sges; + attr->max_mr = le32_to_cpu(sb->max_mr); + attr->max_mr = min_t(u32, attr->max_mr, BNXT_RE_MAX_MRW_SUPPORTED(chip_gen)); + attr->max_mw = le32_to_cpu(sb->max_mw); + attr->max_mw = min_t(u32, attr->max_mw, BNXT_RE_MAX_MRW_SUPPORTED(chip_gen)); + + attr->max_mr_size = le64_to_cpu(sb->max_mr_size); + attr->max_pd = BNXT_QPLIB_MAX_PD; + attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); + attr->max_ah = le32_to_cpu(sb->max_ah); + attr->max_ah = min_t(u32, attr->max_ah, BNXT_RE_MAX_AH_SUPPORTED(chip_gen)); + + attr->max_fmr = le32_to_cpu(sb->max_fmr); + attr->max_map_per_fmr = sb->max_map_per_fmr; + + attr->max_srq = le16_to_cpu(sb->max_srq); + attr->max_srq = min_t(u32, attr->max_srq, BNXT_RE_MAX_SRQ_SUPPORTED(chip_gen)); + attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; + attr->max_srq_sges = sb->max_srq_sge; + attr->max_pkey = 1; + + attr->max_inline_data = !cctx->modes.wqe_mode ? + le32_to_cpu(sb->max_inline_data) : + le16_to_cpu(sb->max_inline_data_var_wqe); + if (!_is_chip_p7(cctx)) { + attr->l2_db_size = (sb->l2_db_space_size + 1) * + (0x01 << RCFW_DBR_BASE_PAGE_SHIFT); + } + attr->max_sgid = le32_to_cpu(sb->max_gid); + + /* TODO: remove this hack for statically allocated gid_map */ + bnxt_re_set_max_gid(&attr->max_sgid); + + attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags); + attr->page_size_cap = BIT_ULL(28) | BIT_ULL(21) | BIT_ULL(12); + + bnxt_qplib_query_version(rcfw, attr->fw_ver); + + for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { + temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); + tqm_alloc = (u8 *)&temp; + attr->tqm_alloc_reqs[i * 4] = *tqm_alloc; + attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc); + attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); + attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); + } + + if (rcfw->res->cctx->hwrm_intf_ver >= HWRM_VERSION_DEV_ATTR_MAX_DPI) + attr->max_dpi = le32_to_cpu(sb->max_dpi); + + attr->is_atomic = bnxt_qplib_is_atomic_cap(rcfw); +bail: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + return rc; +} + +int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res) +{ + struct creq_set_func_resources_resp resp = {}; + struct cmdq_set_func_resources req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_rcfw *rcfw; + struct bnxt_qplib_ctx *hctx; + int rc = 0; + + rcfw = res->rcfw; + hctx = res->hctx; + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_SET_FUNC_RESOURCES, + sizeof(req)); + + req.number_of_qp = cpu_to_le32(hctx->qp_ctx.max); + req.number_of_mrw = cpu_to_le32(hctx->mrw_ctx.max); + req.number_of_srq = cpu_to_le32(hctx->srq_ctx.max); + req.number_of_cq = cpu_to_le32(hctx->cq_ctx.max); + + req.max_qp_per_vf = cpu_to_le32(hctx->vf_res.max_qp); + req.max_mrw_per_vf = cpu_to_le32(hctx->vf_res.max_mrw); + req.max_srq_per_vf = cpu_to_le32(hctx->vf_res.max_srq); + req.max_cq_per_vf = cpu_to_le32(hctx->vf_res.max_cq); + req.max_gid_per_vf = cpu_to_le32(hctx->vf_res.max_gid); + + /* Keep the old stats context id of PF */ + req.stat_ctx_id = cpu_to_le32(hctx->stats.fw_id); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + dev_err(&res->pdev->dev, + "QPLIB: Failed to set function resources\n"); + + return rc; +} + +int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + struct bnxt_qplib_gid *gid, u16 gid_idx, const u8 *smac) +{ + struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, + struct bnxt_qplib_res, + sgid_tbl); + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_modify_gid_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_modify_gid req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_MODIFY_GID, + sizeof(req)); + + req.gid[0] = cpu_to_be32(((u32 *)gid->data)[3]); + req.gid[1] = cpu_to_be32(((u32 *)gid->data)[2]); + req.gid[2] = cpu_to_be32(((u32 *)gid->data)[1]); + req.gid[3] = cpu_to_be32(((u32 *)gid->data)[0]); + if (res->prio) { + req.vlan |= cpu_to_le16(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | + CMDQ_ADD_GID_VLAN_VLAN_EN); + } + + /* MAC in network format */ + req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); + req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); + req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); + req.gid_index = cpu_to_le16(gid_idx); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) { + dev_err(&res->pdev->dev, + "QPLIB: update SGID table failed\n"); + return rc; + } + return 0; +} + +/* SGID */ +int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, + struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, + struct bnxt_qplib_gid *gid) +{ + if (index > sgid_tbl->max) { + dev_err(&res->pdev->dev, + "QPLIB: Index %d exceeded SGID table max (%d)\n", + index, sgid_tbl->max); + return -EINVAL; + } + memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid)); + return 0; +} + +int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + struct bnxt_qplib_gid *gid, + u16 vlan_id, bool update) +{ + struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, + struct bnxt_qplib_res, + sgid_tbl); + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + int index; + + if (sgid_tbl == NULL) { + dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated\n"); + return -EINVAL; + } + /* Do we need a sgid_lock here? */ + if (!sgid_tbl->active) { + dev_err(&res->pdev->dev, + "QPLIB: SGID table has no active entries\n"); + return -ENOMEM; + } + for (index = 0; index < sgid_tbl->max; index++) { + if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) && + vlan_id == sgid_tbl->tbl[index].vlan_id) + break; + } + if (index == sgid_tbl->max) { + dev_warn(&res->pdev->dev, "GID not found in the SGID table\n"); + return 0; + } + + if (update) { + struct creq_delete_gid_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_delete_gid req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DELETE_GID, + sizeof(req)); + if (sgid_tbl->hw_id[index] == 0xFFFF) { + dev_err(&res->pdev->dev, + "QPLIB: GID entry contains an invalid HW id"); + return -EINVAL; + } + req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + } + memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero, + sizeof(bnxt_qplib_gid_zero)); + sgid_tbl->tbl[index].vlan_id = 0xFFFF; + sgid_tbl->vlan[index] = false; + sgid_tbl->active--; + dev_dbg(&res->pdev->dev, + "QPLIB: SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n", + index, sgid_tbl->hw_id[index], sgid_tbl->active); + sgid_tbl->hw_id[index] = (u16)-1; + + return 0; +} + +int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + const union ib_gid *gid, const u8 *smac, u16 vlan_id, + bool update, u32 *index) +{ + struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl, + struct bnxt_qplib_res, + sgid_tbl); + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + int i, free_idx; + + if (sgid_tbl == NULL) { + dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated\n"); + return -EINVAL; + } + /* Do we need a sgid_lock here? */ + if (sgid_tbl->active == sgid_tbl->max) { + dev_err(&res->pdev->dev, "QPLIB: SGID table is full\n"); + return -ENOMEM; + } + free_idx = sgid_tbl->max; + for (i = 0; i < sgid_tbl->max; i++) { + if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) && + sgid_tbl->tbl[i].vlan_id == vlan_id) { + dev_dbg(&res->pdev->dev, + "QPLIB: SGID entry already exist in entry %d!\n", + i); + *index = i; + return -EALREADY; + } else if (!memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero, + sizeof(bnxt_qplib_gid_zero)) && + free_idx == sgid_tbl->max) { + free_idx = i; + } + } + if (free_idx == sgid_tbl->max) { + dev_err(&res->pdev->dev, + "QPLIB: SGID table is FULL but count is not MAX??\n"); + return -ENOMEM; + } + if (update) { + struct creq_add_gid_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_add_gid req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_ADD_GID, + sizeof(req)); + + req.gid[0] = cpu_to_be32(((u32 *)gid->raw)[3]); + req.gid[1] = cpu_to_be32(((u32 *)gid->raw)[2]); + req.gid[2] = cpu_to_be32(((u32 *)gid->raw)[1]); + req.gid[3] = cpu_to_be32(((u32 *)gid->raw)[0]); + /* driver should ensure that all RoCE traffic is always VLAN tagged + * if RoCE traffic is running on non-zero VLAN ID or + * RoCE traffic is running on non-zero Priority. + */ + if ((vlan_id != 0xFFFF) || res->prio) { + if (vlan_id != 0xFFFF) + req.vlan = cpu_to_le16(vlan_id & + CMDQ_ADD_GID_VLAN_VLAN_ID_MASK); + req.vlan |= + cpu_to_le16(CMDQ_ADD_GID_VLAN_TPID_TPID_8100 | + CMDQ_ADD_GID_VLAN_VLAN_EN); + } + + /* MAC in network format */ + req.src_mac[0] = cpu_to_be16(((u16 *)smac)[0]); + req.src_mac[1] = cpu_to_be16(((u16 *)smac)[1]); + req.src_mac[2] = cpu_to_be16(((u16 *)smac)[2]); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid); + } + + if (vlan_id != 0xFFFF) + sgid_tbl->vlan[free_idx] = true; + + memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); + sgid_tbl->tbl[free_idx].vlan_id = vlan_id; + sgid_tbl->active++; + dev_dbg(&res->pdev->dev, + "QPLIB: SGID added hw_id[0x%x] = 0x%x active = 0x%x\n", + free_idx, sgid_tbl->hw_id[free_idx], sgid_tbl->active); + + *index = free_idx; + /* unlock */ + return 0; +} + +/* AH */ +int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_create_ah_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_create_ah req = {}; + u32 temp32[4]; + u16 temp16[3]; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_CREATE_AH, + sizeof(req)); + + memcpy(temp32, ah->dgid.data, sizeof(struct bnxt_qplib_gid)); + req.dgid[0] = cpu_to_le32(temp32[0]); + req.dgid[1] = cpu_to_le32(temp32[1]); + req.dgid[2] = cpu_to_le32(temp32[2]); + req.dgid[3] = cpu_to_le32(temp32[3]); + + req.type = ah->nw_type; + req.hop_limit = ah->hop_limit; + req.sgid_index = cpu_to_le16(res->sgid_tbl.hw_id[ah->sgid_index]); + req.dest_vlan_id_flow_label = cpu_to_le32((ah->flow_label & + CMDQ_CREATE_AH_FLOW_LABEL_MASK) | + CMDQ_CREATE_AH_DEST_VLAN_ID_MASK); + req.pd_id = cpu_to_le32(ah->pd->id); + req.traffic_class = ah->traffic_class; + + /* MAC in network format */ + memcpy(temp16, ah->dmac, ETH_ALEN); + req.dest_mac[0] = cpu_to_le16(temp16[0]); + req.dest_mac[1] = cpu_to_le16(temp16[1]); + req.dest_mac[2] = cpu_to_le16(temp16[2]); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), block); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + + ah->id = le32_to_cpu(resp.xid); + /* for Cu/Wh AHID 0 is not valid */ + if (!_is_chip_gen_p5_p7(res->cctx) && !ah->id) + rc = -EINVAL; + + return rc; +} + +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_destroy_ah_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_ah req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DESTROY_AH, + sizeof(req)); + + req.ah_cid = cpu_to_le32(ah->id); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), block); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + return rc; +} + +/* MRW */ +int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) +{ + struct creq_deallocate_key_resp resp = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct cmdq_deallocate_key req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + int rc; + + if (mrw->lkey == 0xFFFFFFFF) { + dev_info(&res->pdev->dev, + "QPLIB: SP: Free a reserved lkey MRW\n"); + return 0; + } + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DEALLOCATE_KEY, + sizeof(req)); + + req.mrw_flags = mrw->type; + + if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || + (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || + (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) + req.key = cpu_to_le32(mrw->rkey); + else + req.key = cpu_to_le32(mrw->lkey); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + + if (mrw->hwq.max_elements) + bnxt_qplib_free_hwq(res, &mrw->hwq); + + return 0; +} + +int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_allocate_mrw_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_allocate_mrw req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_ALLOCATE_MRW, + sizeof(req)); + + req.pd_id = cpu_to_le32(mrw->pd->id); + req.mrw_flags = mrw->type; + if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR && + mrw->flags & BNXT_QPLIB_FR_PMR) || + mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A || + mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B) + req.access = CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY; + req.mrw_handle = cpu_to_le64((uintptr_t)mrw); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || + (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || + (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) + mrw->rkey = le32_to_cpu(resp.xid); + else + mrw->lkey = le32_to_cpu(resp.xid); + + return 0; +} + +int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, + bool block) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_deregister_mr_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_deregister_mr req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_DEREGISTER_MR, + sizeof(req)); + + req.lkey = cpu_to_le32(mrw->lkey); + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), block); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + return rc; + + if (mrw->hwq.max_elements) { + mrw->va = 0; + mrw->total_size = 0; + bnxt_qplib_free_hwq(res, &mrw->hwq); + } + + return 0; +} + +int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, + struct bnxt_qplib_mrinfo *mrinfo, + bool block) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_register_mr_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_register_mr req = {}; + struct bnxt_qplib_mrw *mr; + u32 buf_pg_size; + u32 pg_size; + u16 level; + u16 flags; + int rc; + + mr = mrinfo->mrw; + buf_pg_size = 0x01ULL << mrinfo->sg.pgshft; + if (mrinfo->sg.npages) { + /* Free the hwq if it already exist, must be a rereg */ + if (mr->hwq.max_elements) + bnxt_qplib_free_hwq(res, &mr->hwq); + /* Use system PAGE_SIZE */ + hwq_attr.res = res; + hwq_attr.depth = mrinfo->sg.npages; + hwq_attr.stride = PAGE_SIZE; + hwq_attr.type = HWQ_TYPE_MR; + hwq_attr.sginfo = &mrinfo->sg; + rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr); + if (rc) { + dev_err(&res->pdev->dev, + "SP: Reg MR memory allocation failed\n"); + return -ENOMEM; + } + } + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_REGISTER_MR, + sizeof(req)); + /* Configure the request */ + if (mrinfo->is_dma) { + /* No PBL provided, just use system PAGE_SIZE */ + level = 0; + req.pbl = 0; + pg_size = PAGE_SIZE; + } else { + level = mr->hwq.level; + req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); + } + + pg_size = buf_pg_size ? buf_pg_size : PAGE_SIZE; + req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | + ((ilog2(pg_size) << + CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & + CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); + req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) << + CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) & + CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK)); + req.access = (mr->flags & 0xFFFF); + req.va = cpu_to_le64(mr->va); + req.key = cpu_to_le32(mr->lkey); + if (_is_alloc_mr_unified(res->dattr)) { + flags = 0; + req.key = cpu_to_le32(mr->pd->id); + flags |= CMDQ_REGISTER_MR_FLAGS_ALLOC_MR; + req.flags = cpu_to_le16(flags); + } + req.mr_size = cpu_to_le64(mr->total_size); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), block); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto fail; + + if (_is_alloc_mr_unified(res->dattr)) { + mr->lkey = le32_to_cpu(resp.xid); + mr->rkey = mr->lkey; + } + + return 0; +fail: + if (mr->hwq.max_elements) + bnxt_qplib_free_hwq(res, &mr->hwq); + return rc; +} + +int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, + struct bnxt_qplib_frpl *frpl, + int max_pg_ptrs) +{ + struct bnxt_qplib_hwq_attr hwq_attr = {}; + struct bnxt_qplib_sg_info sginfo = {}; + int pg_ptrs, rc; + + /* Re-calculate the max to fit the HWQ allocation model */ + pg_ptrs = roundup_pow_of_two(max_pg_ptrs); + + sginfo.pgsize = PAGE_SIZE; + sginfo.nopte = true; + + hwq_attr.res = res; + hwq_attr.depth = pg_ptrs; + hwq_attr.stride = PAGE_SIZE; + hwq_attr.sginfo = &sginfo; + hwq_attr.type = HWQ_TYPE_CTX; + rc = bnxt_qplib_alloc_init_hwq(&frpl->hwq, &hwq_attr); + if (!rc) + frpl->max_pg_ptrs = pg_ptrs; + + return rc; +} + +void bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, + struct bnxt_qplib_frpl *frpl) +{ + bnxt_qplib_free_hwq(res, &frpl->hwq); +} + +int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) +{ + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_map_tc_to_cos_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_map_tc_to_cos req = {}; + int rc; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_MAP_TC_TO_COS, + sizeof(req)); + req.cos0 = cpu_to_le16(cids[0]); + req.cos1 = cpu_to_le16(cids[1]); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + return rc; +} + +static void bnxt_qplib_fill_cc_gen1(struct cmdq_modify_roce_cc_gen1_tlv *ext_req, + struct bnxt_qplib_cc_param_ext *cc_ext) +{ + ext_req->modify_mask = cpu_to_le64(cc_ext->ext_mask); + cc_ext->ext_mask = 0; + ext_req->inactivity_th_hi = cpu_to_le16(cc_ext->inact_th_hi); + ext_req->min_time_between_cnps = cpu_to_le16(cc_ext->min_delta_cnp); + ext_req->init_cp = cpu_to_le16(cc_ext->init_cp); + ext_req->tr_update_mode = cc_ext->tr_update_mode; + ext_req->tr_update_cycles = cc_ext->tr_update_cyls; + ext_req->fr_num_rtts = cc_ext->fr_rtt; + ext_req->ai_rate_increase = cc_ext->ai_rate_incr; + ext_req->reduction_relax_rtts_th = cpu_to_le16(cc_ext->rr_rtt_th); + ext_req->additional_relax_cr_th = cpu_to_le16(cc_ext->ar_cr_th); + ext_req->cr_min_th = cpu_to_le16(cc_ext->cr_min_th); + ext_req->bw_avg_weight = cc_ext->bw_avg_weight; + ext_req->actual_cr_factor = cc_ext->cr_factor; + ext_req->max_cp_cr_th = cpu_to_le16(cc_ext->cr_th_max_cp); + ext_req->cp_bias_en = cc_ext->cp_bias_en; + ext_req->cp_bias = cc_ext->cp_bias; + ext_req->cnp_ecn = cc_ext->cnp_ecn; + ext_req->rtt_jitter_en = cc_ext->rtt_jitter_en; + ext_req->link_bytes_per_usec = cpu_to_le16(cc_ext->bytes_per_usec); + ext_req->reset_cc_cr_th = cpu_to_le16(cc_ext->cc_cr_reset_th); + ext_req->cr_width = cc_ext->cr_width; + ext_req->quota_period_min = cc_ext->min_quota; + ext_req->quota_period_max = cc_ext->max_quota; + ext_req->quota_period_abs_max = cc_ext->abs_max_quota; + ext_req->tr_lower_bound = cpu_to_le16(cc_ext->tr_lb); + ext_req->cr_prob_factor = cc_ext->cr_prob_fac; + ext_req->tr_prob_factor = cc_ext->tr_prob_fac; + ext_req->fairness_cr_th = cpu_to_le16(cc_ext->fair_cr_th); + ext_req->red_div = cc_ext->red_div; + ext_req->cnp_ratio_th = cc_ext->cnp_ratio_th; + ext_req->exp_ai_rtts = cpu_to_le16(cc_ext->ai_ext_rtt); + ext_req->exp_ai_cr_cp_ratio = cc_ext->exp_crcp_ratio; + ext_req->use_rate_table = cc_ext->low_rate_en; + ext_req->cp_exp_update_th = cpu_to_le16(cc_ext->cpcr_update_th); + ext_req->high_exp_ai_rtts_th1 = cpu_to_le16(cc_ext->ai_rtt_th1); + ext_req->high_exp_ai_rtts_th2 = cpu_to_le16(cc_ext->ai_rtt_th2); + ext_req->actual_cr_cong_free_rtts_th = cpu_to_le16(cc_ext->cf_rtt_th); + ext_req->severe_cong_cr_th1 = cpu_to_le16(cc_ext->sc_cr_th1); + ext_req->severe_cong_cr_th2 = cpu_to_le16(cc_ext->sc_cr_th2); + ext_req->link64B_per_rtt = cpu_to_le32(cc_ext->l64B_per_rtt); + ext_req->cc_ack_bytes = cc_ext->cc_ack_bytes; + ext_req->reduce_init_cong_free_rtts_th = cpu_to_le16(cc_ext->reduce_cf_rtt_th); +} + +int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res, + struct bnxt_qplib_cc_param *cc_param) +{ + struct bnxt_qplib_tlv_modify_cc_req tlv_req = {}; + struct creq_modify_roce_cc_resp resp = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_modify_roce_cc *req; + int req_size; + void *cmd; + int rc; + + /* Prepare the older base command */ + req = &tlv_req.base_req; + cmd = req; + req_size = sizeof(*req); + bnxt_qplib_rcfw_cmd_prep(req, CMDQ_BASE_OPCODE_MODIFY_ROCE_CC, + sizeof(*req)); + req->modify_mask = cpu_to_le32(cc_param->mask); + req->enable_cc = cc_param->enable; + req->g = cc_param->g; + req->num_phases_per_state = cc_param->nph_per_state; + req->time_per_phase = cc_param->time_pph; + req->pkts_per_phase = cc_param->pkts_pph; + req->init_cr = cpu_to_le16(cc_param->init_cr); + req->init_tr = cpu_to_le16(cc_param->init_tr); + req->tos_dscp_tos_ecn = (cc_param->tos_dscp << + CMDQ_MODIFY_ROCE_CC_TOS_DSCP_SFT) | + (cc_param->tos_ecn & + CMDQ_MODIFY_ROCE_CC_TOS_ECN_MASK); + req->alt_vlan_pcp = cc_param->alt_vlan_pcp; + req->alt_tos_dscp = cpu_to_le16(cc_param->alt_tos_dscp); + req->rtt = cpu_to_le16(cc_param->rtt); + req->tcp_cp = cpu_to_le16(cc_param->tcp_cp); + req->cc_mode = cc_param->cc_mode; + req->inactivity_th = cpu_to_le16(cc_param->inact_th); + + /* For chip gen P5 onwards fill extended cmd and header */ + if (_is_chip_gen_p5_p7(res->cctx)) { + struct roce_tlv *hdr; + u32 payload; + u32 chunks; + + cmd = &tlv_req; + req_size = sizeof(tlv_req); + /* Prepare primary tlv header */ + hdr = &tlv_req.tlv_hdr; + chunks = CHUNKS(sizeof(struct bnxt_qplib_tlv_modify_cc_req)); + payload = sizeof(struct cmdq_modify_roce_cc); + ROCE_1ST_TLV_PREP(hdr, chunks, payload, true); + /* Prepare secondary tlv header */ + hdr = (struct roce_tlv *)&tlv_req.ext_req; + payload = sizeof(struct cmdq_modify_roce_cc_gen1_tlv) - + sizeof(struct roce_tlv); + ROCE_EXT_TLV_PREP(hdr, TLV_TYPE_MODIFY_ROCE_CC_GEN1, payload, + false, true); + bnxt_qplib_fill_cc_gen1(&tlv_req.ext_req, &cc_param->cc_ext); + } + + bnxt_qplib_fill_cmdqmsg(&msg, cmd, &resp, NULL, req_size, + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(res->rcfw, &msg); + return rc; +} + +static void bnxt_qplib_read_cc_gen1(struct bnxt_qplib_cc_param_ext *cc_ext, + struct creq_query_roce_cc_gen1_resp_sb_tlv *sb) +{ + cc_ext->inact_th_hi = le16_to_cpu(sb->inactivity_th_hi); + cc_ext->min_delta_cnp = le16_to_cpu(sb->min_time_between_cnps); + cc_ext->init_cp = le16_to_cpu(sb->init_cp); + cc_ext->tr_update_mode = sb->tr_update_mode; + cc_ext->tr_update_cyls = sb->tr_update_cycles; + cc_ext->fr_rtt = sb->fr_num_rtts; + cc_ext->ai_rate_incr = sb->ai_rate_increase; + cc_ext->rr_rtt_th = le16_to_cpu(sb->reduction_relax_rtts_th); + cc_ext->ar_cr_th = le16_to_cpu(sb->additional_relax_cr_th); + cc_ext->cr_min_th = le16_to_cpu(sb->cr_min_th); + cc_ext->bw_avg_weight = sb->bw_avg_weight; + cc_ext->cr_factor = sb->actual_cr_factor; + cc_ext->cr_th_max_cp = le16_to_cpu(sb->max_cp_cr_th); + cc_ext->cp_bias_en = sb->cp_bias_en; + cc_ext->cp_bias = sb->cp_bias; + cc_ext->cnp_ecn = sb->cnp_ecn; + cc_ext->rtt_jitter_en = sb->rtt_jitter_en; + cc_ext->bytes_per_usec = le16_to_cpu(sb->link_bytes_per_usec); + cc_ext->cc_cr_reset_th = le16_to_cpu(sb->reset_cc_cr_th); + cc_ext->cr_width = sb->cr_width; + cc_ext->min_quota = sb->quota_period_min; + cc_ext->max_quota = sb->quota_period_max; + cc_ext->abs_max_quota = sb->quota_period_abs_max; + cc_ext->tr_lb = le16_to_cpu(sb->tr_lower_bound); + cc_ext->cr_prob_fac = sb->cr_prob_factor; + cc_ext->tr_prob_fac = sb->tr_prob_factor; + cc_ext->fair_cr_th = le16_to_cpu(sb->fairness_cr_th); + cc_ext->red_div = sb->red_div; + cc_ext->cnp_ratio_th = sb->cnp_ratio_th; + cc_ext->ai_ext_rtt = le16_to_cpu(sb->exp_ai_rtts); + cc_ext->exp_crcp_ratio = sb->exp_ai_cr_cp_ratio; + cc_ext->low_rate_en = sb->use_rate_table; + cc_ext->cpcr_update_th = le16_to_cpu(sb->cp_exp_update_th); + cc_ext->ai_rtt_th1 = le16_to_cpu(sb->high_exp_ai_rtts_th1); + cc_ext->ai_rtt_th2 = le16_to_cpu(sb->high_exp_ai_rtts_th2); + cc_ext->cf_rtt_th = le16_to_cpu(sb->actual_cr_cong_free_rtts_th); + cc_ext->sc_cr_th1 = le16_to_cpu(sb->severe_cong_cr_th1); + cc_ext->sc_cr_th2 = le16_to_cpu(sb->severe_cong_cr_th2); + cc_ext->l64B_per_rtt = le32_to_cpu(sb->link64B_per_rtt); + cc_ext->cc_ack_bytes = sb->cc_ack_bytes; + cc_ext->reduce_cf_rtt_th = le16_to_cpu(sb->reduce_init_cong_free_rtts_th); +} + +int bnxt_qplib_query_cc_param(struct bnxt_qplib_res *res, + struct bnxt_qplib_cc_param *cc_param) +{ + struct creq_query_roce_cc_gen1_resp_sb_tlv *gen1_sb; + struct bnxt_qplib_tlv_query_rcc_sb *ext_sb; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct creq_query_roce_cc_resp resp = {}; + struct creq_query_roce_cc_resp_sb *sb; + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_query_roce_cc req = {}; + struct bnxt_qplib_rcfw_sbuf sbuf; + size_t resp_size; + int rc; + + /* Query the parameters from chip */ + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_ROCE_CC, + sizeof(req)); + if (_is_chip_gen_p5_p7(res->cctx)) + resp_size = sizeof(*ext_sb); + else + resp_size = sizeof(*sb); + sbuf.size = ALIGN(resp_size, BNXT_QPLIB_CMDQE_UNITS); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) + return -ENOMEM; + + req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(res->rcfw, &msg); + if (rc) { + dev_dbg(&res->pdev->dev, "%s:Query CC param failed:0x%x\n", + __func__, rc); + goto out; + } + + ext_sb = sbuf.sb; + gen1_sb = &ext_sb->gen1_sb; + sb = _is_chip_gen_p5_p7(res->cctx) ? &ext_sb->base_sb : + (struct creq_query_roce_cc_resp_sb *)ext_sb; + + cc_param->enable = sb->enable_cc & CREQ_QUERY_ROCE_CC_RESP_SB_ENABLE_CC; + cc_param->tos_ecn = (sb->tos_dscp_tos_ecn & + CREQ_QUERY_ROCE_CC_RESP_SB_TOS_ECN_MASK) >> + CREQ_QUERY_ROCE_CC_RESP_SB_TOS_ECN_SFT; + cc_param->tos_dscp = (sb->tos_dscp_tos_ecn & + CREQ_QUERY_ROCE_CC_RESP_SB_TOS_DSCP_MASK) >> + CREQ_QUERY_ROCE_CC_RESP_SB_TOS_DSCP_SFT; + cc_param->alt_tos_dscp = sb->alt_tos_dscp; + cc_param->alt_vlan_pcp = sb->alt_vlan_pcp; + + cc_param->g = sb->g; + cc_param->nph_per_state = sb->num_phases_per_state; + cc_param->init_cr = le16_to_cpu(sb->init_cr); + cc_param->init_tr = le16_to_cpu(sb->init_tr); + cc_param->cc_mode = sb->cc_mode; + cc_param->inact_th = le16_to_cpu(sb->inactivity_th); + cc_param->rtt = le16_to_cpu(sb->rtt); + cc_param->tcp_cp = le16_to_cpu(sb->tcp_cp); + cc_param->time_pph = sb->time_per_phase; + cc_param->pkts_pph = sb->pkts_per_phase; + if (_is_chip_gen_p5_p7(res->cctx)) + bnxt_qplib_read_cc_gen1(&cc_param->cc_ext, gen1_sb); +out: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + return rc; +} + + +int bnxt_qplib_get_roce_error_stats(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_roce_stats *stats, + struct bnxt_qplib_query_stats_info *sinfo) +{ + struct creq_query_roce_stats_resp resp = {}; + struct creq_query_roce_stats_resp_sb *sb; + struct cmdq_query_roce_stats req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_rcfw_sbuf sbuf; + u16 cmd_flags = 0; + u32 fn_id = 0; + int rc = 0; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_QUERY_ROCE_STATS, + sizeof(req)); + + sbuf.size = sizeof(*sb); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) + return -ENOMEM; + sb = sbuf.sb; + + if (rcfw->res->cctx->hwrm_intf_ver >= HWRM_VERSION_ROCE_STATS_FN_ID) { + if (sinfo->function_id != 0xFFFFFFFF) { + cmd_flags = CMDQ_QUERY_ROCE_STATS_FLAGS_FUNCTION_ID; + if (sinfo->vf_valid) { + fn_id = CMDQ_QUERY_ROCE_STATS_VF_VALID; + fn_id |= (sinfo->function_id << + CMDQ_QUERY_ROCE_STATS_VF_NUM_SFT) & + CMDQ_QUERY_ROCE_STATS_VF_NUM_MASK; + } else { + fn_id = sinfo->function_id & + CMDQ_QUERY_ROCE_STATS_PF_NUM_MASK; + } + } + + req.flags = cpu_to_le16(cmd_flags); + req.function_id = cpu_to_le32(fn_id); + + if (sinfo->collection_id != 0xFF) { + cmd_flags |= CMDQ_QUERY_ROCE_STATS_FLAGS_COLLECTION_ID; + req.collection_id = sinfo->collection_id; + } + } else { + /* For older HWRM version, the command length has to be + * adjusted. 8 bytes are more in the newer command. + * So subtract these 8 bytes for older HWRM version. + * command units are adjusted inside + * bnxt_qplib_rcfw_send_message. + */ + req.cmd_size -= 8; + } + + req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS; + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto bail; + /* Extract the context from the side buffer */ + stats->to_retransmits = le64_to_cpu(sb->to_retransmits); + stats->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); + stats->max_retry_exceeded = le64_to_cpu(sb->max_retry_exceeded); + stats->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); + stats->missing_resp = le64_to_cpu(sb->missing_resp); + stats->unrecoverable_err = le64_to_cpu(sb->unrecoverable_err); + stats->bad_resp_err = le64_to_cpu(sb->bad_resp_err); + stats->local_qp_op_err = le64_to_cpu(sb->local_qp_op_err); + stats->local_protection_err = le64_to_cpu(sb->local_protection_err); + stats->mem_mgmt_op_err = le64_to_cpu(sb->mem_mgmt_op_err); + stats->remote_invalid_req_err = le64_to_cpu(sb->remote_invalid_req_err); + stats->remote_access_err = le64_to_cpu(sb->remote_access_err); + stats->remote_op_err = le64_to_cpu(sb->remote_op_err); + stats->dup_req = le64_to_cpu(sb->dup_req); + stats->res_exceed_max = le64_to_cpu(sb->res_exceed_max); + stats->res_length_mismatch = le64_to_cpu(sb->res_length_mismatch); + stats->res_exceeds_wqe = le64_to_cpu(sb->res_exceeds_wqe); + stats->res_opcode_err = le64_to_cpu(sb->res_opcode_err); + stats->res_rx_invalid_rkey = le64_to_cpu(sb->res_rx_invalid_rkey); + stats->res_rx_domain_err = le64_to_cpu(sb->res_rx_domain_err); + stats->res_rx_no_perm = le64_to_cpu(sb->res_rx_no_perm); + stats->res_rx_range_err = le64_to_cpu(sb->res_rx_range_err); + stats->res_tx_invalid_rkey = le64_to_cpu(sb->res_tx_invalid_rkey); + stats->res_tx_domain_err = le64_to_cpu(sb->res_tx_domain_err); + stats->res_tx_no_perm = le64_to_cpu(sb->res_tx_no_perm); + stats->res_tx_range_err = le64_to_cpu(sb->res_tx_range_err); + stats->res_irrq_oflow = le64_to_cpu(sb->res_irrq_oflow); + stats->res_unsup_opcode = le64_to_cpu(sb->res_unsup_opcode); + stats->res_unaligned_atomic = le64_to_cpu(sb->res_unaligned_atomic); + stats->res_rem_inv_err = le64_to_cpu(sb->res_rem_inv_err); + stats->res_mem_error = le64_to_cpu(sb->res_mem_error); + stats->res_srq_err = le64_to_cpu(sb->res_srq_err); + stats->res_cmp_err = le64_to_cpu(sb->res_cmp_err); + stats->res_invalid_dup_rkey = le64_to_cpu(sb->res_invalid_dup_rkey); + stats->res_wqe_format_err = le64_to_cpu(sb->res_wqe_format_err); + stats->res_cq_load_err = le64_to_cpu(sb->res_cq_load_err); + stats->res_srq_load_err = le64_to_cpu(sb->res_srq_load_err); + stats->res_tx_pci_err = le64_to_cpu(sb->res_tx_pci_err); + stats->res_rx_pci_err = le64_to_cpu(sb->res_rx_pci_err); + + if (!rcfw->init_oos_stats) { + rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); + rcfw->init_oos_stats = true; + } else { + stats->res_oos_drop_count += (le64_to_cpu(sb->res_oos_drop_count) - + rcfw->oos_prev) & + BNXT_QPLIB_OOS_COUNT_MASK; + rcfw->oos_prev = le64_to_cpu(sb->res_oos_drop_count); + } + + stats->active_qp_count_p0 = le64_to_cpu(sb->active_qp_count_p0); + stats->active_qp_count_p1 = le64_to_cpu(sb->active_qp_count_p1); + stats->active_qp_count_p2 = le64_to_cpu(sb->active_qp_count_p2); + stats->active_qp_count_p3 = le64_to_cpu(sb->active_qp_count_p3); +bail: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + return rc; +} + +int bnxt_qplib_set_link_aggr_mode(struct bnxt_qplib_res *res, + u8 aggr_mode, u8 member_port_map, + u8 active_port_map, bool aggr_en, + u32 stats_fw_id) +{ + struct creq_set_link_aggr_mode_resources_resp resp = {}; + struct cmdq_set_link_aggr_mode_cc req = {}; + struct bnxt_qplib_rcfw *rcfw = res->rcfw; + struct bnxt_qplib_cmdqmsg msg = {}; + int rc = 0; + + bnxt_qplib_rcfw_cmd_prep(&req, CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE, + sizeof(req)); + + req.aggr_enable = aggr_en; + req.active_port_map = active_port_map; + req.member_port_map = member_port_map; + req.link_aggr_mode = aggr_mode; + + /* need to specify only second port stats ctx id for now */ + req.stat_ctx_id[1] = cpu_to_le16((u16)(stats_fw_id)); + + req.modify_mask = + cpu_to_le32(CMDQ_SET_LINK_AGGR_MODE_MODIFY_MASK_AGGR_EN | + CMDQ_SET_LINK_AGGR_MODE_MODIFY_MASK_ACTIVE_PORT_MAP | + CMDQ_SET_LINK_AGGR_MODE_MODIFY_MASK_MEMBER_PORT_MAP | + CMDQ_SET_LINK_AGGR_MODE_MODIFY_MASK_AGGR_MODE | + CMDQ_SET_LINK_AGGR_MODE_MODIFY_MASK_STAT_CTX_ID); + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + dev_err(&res->pdev->dev, + "QPLIB: Failed to set link aggr mode, %#x\n", rc); + + return rc; +} + +int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid, + struct bnxt_qplib_ext_stat *estat, + struct bnxt_qplib_query_stats_info *sinfo) +{ + struct creq_query_roce_stats_ext_resp resp = {}; + struct creq_query_roce_stats_ext_resp_sb *sb; + struct cmdq_query_roce_stats_ext req = {}; + struct bnxt_qplib_cmdqmsg msg = {}; + struct bnxt_qplib_rcfw_sbuf sbuf; + int rc; + + sbuf.size = sizeof(*sb); + sbuf.sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf.size, + &sbuf.dma_addr, GFP_KERNEL); + if (!sbuf.sb) { + dev_err(&rcfw->pdev->dev, + "QPLIB: SP: QUERY_ROCE_STATS_EXT alloc sb failed\n"); + return -ENOMEM; + } + sb = sbuf.sb; + + bnxt_qplib_rcfw_cmd_prep(&req, + CMDQ_QUERY_ROCE_STATS_EXT_OPCODE_QUERY_ROCE_STATS, + sizeof(req)); + req.resp_size = sbuf.size; + req.resp_addr = cpu_to_le64(sbuf.dma_addr); + req.flags = cpu_to_le16(CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_FUNCTION_ID); + if (_is_chip_p7(rcfw->res->cctx) && rcfw->res->is_vf) { + if (sinfo->vf_valid) + req.function_id = + cpu_to_le32(CMDQ_QUERY_ROCE_STATS_EXT_VF_VALID | + (fid << CMDQ_QUERY_ROCE_STATS_EXT_VF_NUM_SFT)); + else + req.flags = cpu_to_le16(0); + } else { + req.function_id = cpu_to_le32(fid); + } + + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + if (rc) + goto bail; + + /* dump when dyndbg is enabled */ + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, sb, sizeof(*sb)); + estat->tx_atomic_req = le64_to_cpu(sb->tx_atomic_req_pkts); + estat->tx_read_req = le64_to_cpu(sb->tx_read_req_pkts); + estat->tx_read_res = le64_to_cpu(sb->tx_read_res_pkts); + estat->tx_write_req = le64_to_cpu(sb->tx_write_req_pkts); + estat->tx_send_req = le64_to_cpu(sb->tx_send_req_pkts); + estat->tx_roce_pkts = le64_to_cpu(sb->tx_roce_pkts); + estat->tx_roce_bytes = le64_to_cpu(sb->tx_roce_bytes); + estat->rx_atomic_req = le64_to_cpu(sb->rx_atomic_req_pkts); + estat->rx_read_req = le64_to_cpu(sb->rx_read_req_pkts); + estat->rx_read_res = le64_to_cpu(sb->rx_read_res_pkts); + estat->rx_write_req = le64_to_cpu(sb->rx_write_req_pkts); + estat->rx_send_req = le64_to_cpu(sb->rx_send_req_pkts); + estat->rx_roce_pkts = le64_to_cpu(sb->rx_roce_pkts); + estat->rx_roce_bytes = le64_to_cpu(sb->rx_roce_bytes); + estat->rx_roce_good_pkts = le64_to_cpu(sb->rx_roce_good_pkts); + estat->rx_roce_good_bytes = le64_to_cpu(sb->rx_roce_good_bytes); + estat->rx_out_of_buffer = le64_to_cpu(sb->rx_out_of_buffer_pkts); + estat->rx_out_of_sequence = le64_to_cpu(sb->rx_out_of_sequence_pkts); + estat->tx_cnp = le64_to_cpu(sb->tx_cnp_pkts); + estat->rx_cnp = le64_to_cpu(sb->rx_cnp_pkts); + estat->rx_ecn_marked = le64_to_cpu(sb->rx_ecn_marked_pkts); + estat->seq_err_naks_rcvd = le64_to_cpu(sb->seq_err_naks_rcvd); + estat->rnr_naks_rcvd = le64_to_cpu(sb->rnr_naks_rcvd); + estat->missing_resp = le64_to_cpu(sb->missing_resp); + estat->to_retransmits = le64_to_cpu(sb->to_retransmit); + estat->dup_req = le64_to_cpu(sb->dup_req); + estat->rx_dcn_payload_cut = le64_to_cpu(sb->rx_dcn_payload_cut); + estat->te_bypassed = le64_to_cpu(sb->te_bypassed); +bail: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + return rc; +} diff --git a/sys/dev/bnxt/bnxt_re/qplib_sp.h b/sys/dev/bnxt/bnxt_re/qplib_sp.h new file mode 100644 index 000000000000..e306db3b9d8e --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_sp.h @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: Slow Path Operators (header) + */ + +#ifndef __BNXT_QPLIB_SP_H__ +#define __BNXT_QPLIB_SP_H__ + +#include <rdma/ib_verbs.h> + +#define BNXT_QPLIB_RESERVED_QP_WRS 128 + +/* Resource maximums reported by the firmware */ +struct bnxt_qplib_dev_attr { +#define FW_VER_ARR_LEN 4 + u8 fw_ver[FW_VER_ARR_LEN]; + u16 max_sgid; + u16 max_mrw; + u32 max_qp; +#define BNXT_QPLIB_MAX_OUT_RD_ATOM 126 + u32 max_qp_rd_atom; + u32 max_qp_init_rd_atom; + u32 max_qp_wqes; + u32 max_qp_sges; + u32 max_cq; + /* HW supports only 8K entries in PBL. + * So max CQEs that can be supported per CQ is 1M. + */ +#define BNXT_QPLIB_MAX_CQ_WQES 0xfffff + u32 max_cq_wqes; + u32 max_cq_sges; + u32 max_mr; + u64 max_mr_size; +#define BNXT_QPLIB_MAX_PD (64 * 1024) + u32 max_pd; + u32 max_mw; + u32 max_raw_ethy_qp; + u32 max_ah; + u32 max_fmr; + u32 max_map_per_fmr; + u32 max_srq; + u32 max_srq_wqes; + u32 max_srq_sges; + u32 max_pkey; + u32 max_inline_data; + u32 l2_db_size; + u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ]; + u8 is_atomic; + u16 dev_cap_flags; + u64 page_size_cap; + u32 max_dpi; +}; + +struct bnxt_qplib_pd { + u32 id; +}; + +struct bnxt_qplib_gid { + u8 data[16]; +}; + +struct bnxt_qplib_gid_info { + struct bnxt_qplib_gid gid; + u16 vlan_id; +}; + +struct bnxt_qplib_ah { + struct bnxt_qplib_gid dgid; + struct bnxt_qplib_pd *pd; + u32 id; + u8 sgid_index; + u8 host_sgid_index; /* For Query AH if the hw table and SW table are differnt */ + u8 traffic_class; + u32 flow_label; + u8 hop_limit; + u8 sl; + u8 dmac[6]; + u16 vlan_id; + u8 nw_type; + u8 enable_cc; +}; + +struct bnxt_qplib_mrw { + struct bnxt_qplib_pd *pd; + int type; + u32 flags; +#define BNXT_QPLIB_FR_PMR 0x80000000 + u32 lkey; + u32 rkey; +#define BNXT_QPLIB_RSVD_LKEY 0xFFFFFFFF + u64 va; + u64 total_size; + u32 npages; + u64 mr_handle; + struct bnxt_qplib_hwq hwq; +}; + +struct bnxt_qplib_mrinfo { + struct bnxt_qplib_mrw *mrw; + struct bnxt_qplib_sg_info sg; + u64 *ptes; + bool is_dma; +}; + +struct bnxt_qplib_frpl { + int max_pg_ptrs; + struct bnxt_qplib_hwq hwq; +}; + +struct bnxt_qplib_cc_param_ext { + u64 ext_mask; + u16 inact_th_hi; + u16 min_delta_cnp; + u16 init_cp; + u8 tr_update_mode; + u8 tr_update_cyls; + u8 fr_rtt; + u8 ai_rate_incr; + u16 rr_rtt_th; + u16 ar_cr_th; + u16 cr_min_th; + u8 bw_avg_weight; + u8 cr_factor; + u16 cr_th_max_cp; + u8 cp_bias_en; + u8 cp_bias; + u8 cnp_ecn; + u8 rtt_jitter_en; + u16 bytes_per_usec; + u16 cc_cr_reset_th; + u8 cr_width; + u8 min_quota; + u8 max_quota; + u8 abs_max_quota; + u16 tr_lb; + u8 cr_prob_fac; + u8 tr_prob_fac; + u16 fair_cr_th; + u8 red_div; + u8 cnp_ratio_th; + u16 ai_ext_rtt; + u8 exp_crcp_ratio; + u8 low_rate_en; + u16 cpcr_update_th; + u16 ai_rtt_th1; + u16 ai_rtt_th2; + u16 cf_rtt_th; + u16 sc_cr_th1; /* severe congestion cr threshold 1 */ + u16 sc_cr_th2; /* severe congestion cr threshold 2 */ + u32 l64B_per_rtt; + u8 cc_ack_bytes; + u16 reduce_cf_rtt_th; +}; + +struct bnxt_qplib_cc_param { + u8 alt_vlan_pcp; + u16 alt_tos_dscp; +#define BNXT_QPLIB_USER_DSCP_VALID 0x80 + u8 cnp_dscp_user; + u8 roce_dscp_user; + u8 cc_mode; + u8 enable; + u16 inact_th; + u16 init_cr; + u16 init_tr; + u16 rtt; + u8 g; + u8 nph_per_state; + u8 time_pph; + u8 pkts_pph; + u8 tos_ecn; + u8 tos_dscp; + u8 qp1_tos_dscp; + u16 tcp_cp; + struct bnxt_qplib_cc_param_ext cc_ext; + u8 disable_prio_vlan_tx; + /* Mask used while programming the configfs values */ + u32 mask; + /* Mask used while displaying the configfs values */ + u32 cur_mask; + u8 roce_pri; +#define BNXT_QPLIB_CC_PARAM_MASK_VLAN_TX_DISABLE 0x40000 +#define BNXT_QPLIB_CC_PARAM_MASK_ROCE_PRI 0x80000 + /* prev value to clear dscp table */ + u8 prev_roce_pri; + u8 prev_alt_vlan_pcp; + u8 prev_tos_dscp; + u16 prev_alt_tos_dscp; + /* To track if admin has enabled ECN explicitly */ + u8 admin_enable; +}; + +struct bnxt_qplib_roce_stats { + u64 to_retransmits; + u64 seq_err_naks_rcvd; + /* seq_err_naks_rcvd is 64 b */ + u64 max_retry_exceeded; + /* max_retry_exceeded is 64 b */ + u64 rnr_naks_rcvd; + /* rnr_naks_rcvd is 64 b */ + u64 missing_resp; + u64 unrecoverable_err; + /* unrecoverable_err is 64 b */ + u64 bad_resp_err; + /* bad_resp_err is 64 b */ + u64 local_qp_op_err; + /* local_qp_op_err is 64 b */ + u64 local_protection_err; + /* local_protection_err is 64 b */ + u64 mem_mgmt_op_err; + /* mem_mgmt_op_err is 64 b */ + u64 remote_invalid_req_err; + /* remote_invalid_req_err is 64 b */ + u64 remote_access_err; + /* remote_access_err is 64 b */ + u64 remote_op_err; + /* remote_op_err is 64 b */ + u64 dup_req; + /* dup_req is 64 b */ + u64 res_exceed_max; + /* res_exceed_max is 64 b */ + u64 res_length_mismatch; + /* res_length_mismatch is 64 b */ + u64 res_exceeds_wqe; + /* res_exceeds_wqe is 64 b */ + u64 res_opcode_err; + /* res_opcode_err is 64 b */ + u64 res_rx_invalid_rkey; + /* res_rx_invalid_rkey is 64 b */ + u64 res_rx_domain_err; + /* res_rx_domain_err is 64 b */ + u64 res_rx_no_perm; + /* res_rx_no_perm is 64 b */ + u64 res_rx_range_err; + /* res_rx_range_err is 64 b */ + u64 res_tx_invalid_rkey; + /* res_tx_invalid_rkey is 64 b */ + u64 res_tx_domain_err; + /* res_tx_domain_err is 64 b */ + u64 res_tx_no_perm; + /* res_tx_no_perm is 64 b */ + u64 res_tx_range_err; + /* res_tx_range_err is 64 b */ + u64 res_irrq_oflow; + /* res_irrq_oflow is 64 b */ + u64 res_unsup_opcode; + /* res_unsup_opcode is 64 b */ + u64 res_unaligned_atomic; + /* res_unaligned_atomic is 64 b */ + u64 res_rem_inv_err; + /* res_rem_inv_err is 64 b */ + u64 res_mem_error; + /* res_mem_error is 64 b */ + u64 res_srq_err; + /* res_srq_err is 64 b */ + u64 res_cmp_err; + /* res_cmp_err is 64 b */ + u64 res_invalid_dup_rkey; + /* res_invalid_dup_rkey is 64 b */ + u64 res_wqe_format_err; + /* res_wqe_format_err is 64 b */ + u64 res_cq_load_err; + /* res_cq_load_err is 64 b */ + u64 res_srq_load_err; + /* res_srq_load_err is 64 b */ + u64 res_tx_pci_err; + /* res_tx_pci_err is 64 b */ + u64 res_rx_pci_err; + /* res_rx_pci_err is 64 b */ + u64 res_oos_drop_count; + /* res_oos_drop_count */ + u64 active_qp_count_p0; + /* port 0 active qps */ + u64 active_qp_count_p1; + /* port 1 active qps */ + u64 active_qp_count_p2; + /* port 2 active qps */ + u64 active_qp_count_p3; + /* port 3 active qps */ +}; + +struct bnxt_qplib_ext_stat { + u64 tx_atomic_req; + u64 tx_read_req; + u64 tx_read_res; + u64 tx_write_req; + u64 tx_send_req; + u64 tx_roce_pkts; + u64 tx_roce_bytes; + u64 rx_atomic_req; + u64 rx_read_req; + u64 rx_read_res; + u64 rx_write_req; + u64 rx_send_req; + u64 rx_roce_pkts; + u64 rx_roce_bytes; + u64 rx_roce_good_pkts; + u64 rx_roce_good_bytes; + u64 rx_out_of_buffer; + u64 rx_out_of_sequence; + u64 tx_cnp; + u64 rx_cnp; + u64 rx_ecn_marked; + u64 seq_err_naks_rcvd; + u64 rnr_naks_rcvd; + u64 missing_resp; + u64 to_retransmits; + u64 dup_req; + u64 rx_dcn_payload_cut; + u64 te_bypassed; +}; + +#define BNXT_QPLIB_ACCESS_LOCAL_WRITE (1 << 0) +#define BNXT_QPLIB_ACCESS_REMOTE_READ (1 << 1) +#define BNXT_QPLIB_ACCESS_REMOTE_WRITE (1 << 2) +#define BNXT_QPLIB_ACCESS_REMOTE_ATOMIC (1 << 3) +#define BNXT_QPLIB_ACCESS_MW_BIND (1 << 4) +#define BNXT_QPLIB_ACCESS_ZERO_BASED (1 << 5) +#define BNXT_QPLIB_ACCESS_ON_DEMAND (1 << 6) + +int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res, + struct bnxt_qplib_sgid_tbl *sgid_tbl, int index, + struct bnxt_qplib_gid *gid); +int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + struct bnxt_qplib_gid *gid, u16 vlan_id, bool update); +int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + const union ib_gid *gid, const u8 *mac, u16 vlan_id, + bool update, u32 *index); +int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, + struct bnxt_qplib_gid *gid, u16 gid_idx, const u8 *smac); +int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw); +int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res); +int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block); +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block); +int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw); +int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, + bool block); +int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, + struct bnxt_qplib_mrinfo *mrinfo, bool block); +int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr); +int bnxt_qplib_alloc_fast_reg_mr(struct bnxt_qplib_res *res, + struct bnxt_qplib_mrw *mr, int max); +int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, + struct bnxt_qplib_frpl *frpl, int max); +void bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res *res, + struct bnxt_qplib_frpl *frpl); +int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids); +int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res, + struct bnxt_qplib_cc_param *cc_param); +int bnxt_qplib_query_cc_param(struct bnxt_qplib_res *res, + struct bnxt_qplib_cc_param *cc_param); +int bnxt_qplib_set_link_aggr_mode(struct bnxt_qplib_res *res, + u8 aggr_mode, u8 member_port_map, + u8 active_port_map, bool aggr_en, + u32 stats_fw_id); +int bnxt_qplib_get_roce_error_stats(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_roce_stats *stats, + struct bnxt_qplib_query_stats_info *sinfo); +int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid, + struct bnxt_qplib_ext_stat *estat, + struct bnxt_qplib_query_stats_info *sinfo); +static inline void bnxt_re_set_max_gid(u16 *max_sgid); +bool ib_modify_qp_is_ok_compat(enum ib_qp_state cur_state, enum ib_qp_state next_state, + enum ib_qp_type type, enum ib_qp_attr_mask mask); + +#define BNXT_MAX_SQ_SIZE 0xFFFF +#define BNXT_MAX_VAR_WQE_SIZE 512 +#define BNXT_SGE_SIZE 16 + +/* PF defines */ +#define BNXT_RE_MAX_QP_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (64 * 1024) : 0 + +#define BNXT_RE_MAX_MRW_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (256 * 1024) : 0 + +#define BNXT_RE_MAX_CQ_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (64 * 1024) : 0 + +#define BNXT_RE_MAX_SRQ_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (4 * 1024) : 0 + +#define BNXT_RE_MAX_AH_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (64 * 1024) : 0 + +/* VF defines */ +#define BNXT_RE_VF_MAX_QP_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (6 * 1024) : 0 + +#define BNXT_RE_VF_MAX_MRW_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (6 * 1024) : 0 + +#define BNXT_RE_VF_MAX_CQ_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (6 * 1024) : 0 + +#define BNXT_RE_VF_MAX_SRQ_SUPPORTED(chip_gen) \ + chip_gen == BNXT_RE_DEFAULT ? (4 * 1024) : 0 + +static inline void bnxt_re_set_max_gid(u16 *max_sgid) +{ + *max_sgid = max_t(u32, 256, *max_sgid); + *max_sgid = min_t(u32, 256, *max_sgid); +} + +#endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_tlv.h b/sys/dev/bnxt/bnxt_re/qplib_tlv.h new file mode 100644 index 000000000000..eeaea41a37e6 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/qplib_tlv.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017 - 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 AUTHOR 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 AUTHOR 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 __QPLIB_TLV_H__ +#define __QPLIB_TLV_H__ + +struct roce_tlv { + struct tlv tlv; + u8 total_size; + u8 unused[7]; +}; + +#define CHUNK_SIZE 16 +#define CHUNKS(x) (((x) + CHUNK_SIZE - 1) / CHUNK_SIZE) + +#define ROCE_1ST_TLV_PREP(rtlv, tot_chunks, content_bytes, more) \ + do { \ + (rtlv)->tlv.cmd_discr = CMD_DISCR_TLV_ENCAP; \ + (rtlv)->tlv.tlv_type = TLV_TYPE_ROCE_SP_COMMAND; \ + (rtlv)->tlv.length = (content_bytes); \ + (rtlv)->tlv.flags = TLV_FLAGS_REQUIRED; \ + (rtlv)->tlv.flags |= (more) ? TLV_FLAGS_MORE : 0; \ + (rtlv)->total_size = (tot_chunks); \ + } while (0) + +#define ROCE_EXT_TLV_PREP(rtlv, ext_type, content_bytes, more, reqd) \ + do { \ + (rtlv)->tlv.cmd_discr = CMD_DISCR_TLV_ENCAP; \ + (rtlv)->tlv.tlv_type = (ext_type); \ + (rtlv)->tlv.length = (content_bytes); \ + (rtlv)->tlv.flags |= (more) ? TLV_FLAGS_MORE : 0; \ + (rtlv)->tlv.flags |= (reqd) ? TLV_FLAGS_REQUIRED : 0; \ + } while (0) + +/* + * TLV size in units of 16 byte chunks + */ +#define TLV_SIZE ((sizeof(struct roce_tlv) + 15) / 16) +/* + * TLV length in bytes + */ +#define TLV_BYTES (TLV_SIZE * 16) + +#define HAS_TLV_HEADER(msg) (((struct tlv *)(msg))->cmd_discr == CMD_DISCR_TLV_ENCAP) +#define GET_TLV_DATA(tlv) ((void *)&((uint8_t *)(tlv))[TLV_BYTES]) + +static inline u8 __get_cmdq_base_opcode(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct cmdq_base *)GET_TLV_DATA(req))->opcode; + else + return req->opcode; +} + +static inline void __set_cmdq_base_opcode(struct cmdq_base *req, + u32 size, u8 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->opcode = val; + else + req->opcode = val; +} + +static inline __le16 __get_cmdq_base_cookie(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct cmdq_base *)GET_TLV_DATA(req))->cookie; + else + return req->cookie; +} + +static inline void __set_cmdq_base_cookie(struct cmdq_base *req, + u32 size, __le16 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->cookie = val; + else + req->cookie = val; +} + +static inline __le64 __get_cmdq_base_resp_addr(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct cmdq_base *)GET_TLV_DATA(req))->resp_addr; + else + return req->resp_addr; +} + +static inline void __set_cmdq_base_resp_addr(struct cmdq_base *req, + u32 size, __le64 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->resp_addr = val; + else + req->resp_addr = val; +} + +static inline u8 __get_cmdq_base_resp_size(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct cmdq_base *)GET_TLV_DATA(req))->resp_size; + else + return req->resp_size; +} + +static inline void __set_cmdq_base_resp_size(struct cmdq_base *req, + u32 size, u8 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->resp_size = val; + else + req->resp_size = val; +} + +static inline u8 __get_cmdq_base_cmd_size(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct roce_tlv *)(req))->total_size; + else + return req->cmd_size; +} + +static inline void __set_cmdq_base_cmd_size(struct cmdq_base *req, + u32 size, u8 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->cmd_size = val; + else + req->cmd_size = val; +} + +static inline __le16 __get_cmdq_base_flags(struct cmdq_base *req, u32 size) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + return ((struct cmdq_base *)GET_TLV_DATA(req))->flags; + else + return req->flags; +} + +static inline void __set_cmdq_base_flags(struct cmdq_base *req, + u32 size, __le16 val) +{ + if (HAS_TLV_HEADER(req) && size > TLV_BYTES) + ((struct cmdq_base *)GET_TLV_DATA(req))->flags = val; + else + req->flags = val; +} + +struct bnxt_qplib_tlv_modify_cc_req { + struct roce_tlv tlv_hdr; + struct cmdq_modify_roce_cc base_req; + __le64 tlvpad; + struct cmdq_modify_roce_cc_gen1_tlv ext_req; +}; + +struct bnxt_qplib_tlv_query_rcc_sb { + struct roce_tlv tlv_hdr; + struct creq_query_roce_cc_resp_sb base_sb; + struct creq_query_roce_cc_gen1_resp_sb_tlv gen1_sb; +}; +#endif diff --git a/sys/dev/bnxt/bnxt_re/stats.c b/sys/dev/bnxt/bnxt_re/stats.c new file mode 100644 index 000000000000..7b0e6097aae6 --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/stats.c @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: statistics related functions + */ + +#include "bnxt_re.h" +#include "bnxt.h" + +int bnxt_re_get_flow_stats_from_service_pf(struct bnxt_re_dev *rdev, + struct bnxt_re_flow_counters *stats, + struct bnxt_qplib_query_stats_info *sinfo) +{ + struct hwrm_cfa_flow_stats_output resp = {}; + struct hwrm_cfa_flow_stats_input req = {}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg = {}; + u16 target_id; + int rc = 0; + + if (sinfo->function_id == 0xFFFFFFFF) + target_id = -1; + else + target_id = sinfo->function_id + 1; + + /* Issue HWRM cmd to read flow counters for CNP tx and rx */ + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_CFA_FLOW_STATS, -1, target_id); + req.num_flows = cpu_to_le16(6); + req.flow_handle_0 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT); + req.flow_handle_1 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + req.flow_handle_2 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT); + req.flow_handle_3 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + req.flow_handle_4 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT); + req.flow_handle_5 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + bnxt_re_fill_fw_msg(&fw_msg, &req, sizeof(req), &resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to get CFA Flow stats : rc = 0x%x\n", rc); + return rc; + } + + stats->cnp_stats.cnp_tx_pkts = le64_to_cpu(resp.packet_0); + stats->cnp_stats.cnp_tx_bytes = le64_to_cpu(resp.byte_0); + stats->cnp_stats.cnp_rx_pkts = le64_to_cpu(resp.packet_1); + stats->cnp_stats.cnp_rx_bytes = le64_to_cpu(resp.byte_1); + + stats->ro_stats.tx_pkts = le64_to_cpu(resp.packet_2) + + le64_to_cpu(resp.packet_4); + stats->ro_stats.tx_bytes = le64_to_cpu(resp.byte_2) + + le64_to_cpu(resp.byte_4); + stats->ro_stats.rx_pkts = le64_to_cpu(resp.packet_3) + + le64_to_cpu(resp.packet_5); + stats->ro_stats.rx_bytes = le64_to_cpu(resp.byte_3) + + le64_to_cpu(resp.byte_5); + + return 0; +} + +int bnxt_re_get_qos_stats(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_ro_counters roce_only_tmp[2] = {{}, {}}; + struct bnxt_re_cnp_counters tmp_counters[2] = {{}, {}}; + struct hwrm_cfa_flow_stats_output resp = {}; + struct hwrm_cfa_flow_stats_input req = {}; + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct bnxt_fw_msg fw_msg = {}; + struct bnxt_re_cc_stat *cnps; + struct bnxt_re_rstat *dstat; + int rc = 0; + u64 bytes; + u64 pkts; + + /* Issue HWRM cmd to read flow counters for CNP tx and rx */ + bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_CFA_FLOW_STATS, -1, -1); + req.num_flows = cpu_to_le16(6); + req.flow_handle_0 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT); + req.flow_handle_1 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + req.flow_handle_2 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT); + req.flow_handle_3 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + req.flow_handle_4 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT); + req.flow_handle_5 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT | + HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); + rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); + if (rc) { + dev_err(rdev_to_dev(rdev), + "Failed to get CFA Flow stats : rc = 0x%x\n", rc); + goto done; + } + + tmp_counters[0].cnp_tx_pkts = le64_to_cpu(resp.packet_0); + tmp_counters[0].cnp_tx_bytes = le64_to_cpu(resp.byte_0); + tmp_counters[0].cnp_rx_pkts = le64_to_cpu(resp.packet_1); + tmp_counters[0].cnp_rx_bytes = le64_to_cpu(resp.byte_1); + + roce_only_tmp[0].tx_pkts = le64_to_cpu(resp.packet_2) + + le64_to_cpu(resp.packet_4); + roce_only_tmp[0].tx_bytes = le64_to_cpu(resp.byte_2) + + le64_to_cpu(resp.byte_4); + roce_only_tmp[0].rx_pkts = le64_to_cpu(resp.packet_3) + + le64_to_cpu(resp.packet_5); + roce_only_tmp[0].rx_bytes = le64_to_cpu(resp.byte_3) + + le64_to_cpu(resp.byte_5); + + cnps = &rdev->stats.cnps; + dstat = &rdev->stats.dstat; + if (!cnps->is_first) { + /* First query done.. */ + cnps->is_first = true; + cnps->prev[0].cnp_tx_pkts = tmp_counters[0].cnp_tx_pkts; + cnps->prev[0].cnp_tx_bytes = tmp_counters[0].cnp_tx_bytes; + cnps->prev[0].cnp_rx_pkts = tmp_counters[0].cnp_rx_pkts; + cnps->prev[0].cnp_rx_bytes = tmp_counters[0].cnp_rx_bytes; + + cnps->prev[1].cnp_tx_pkts = tmp_counters[1].cnp_tx_pkts; + cnps->prev[1].cnp_tx_bytes = tmp_counters[1].cnp_tx_bytes; + cnps->prev[1].cnp_rx_pkts = tmp_counters[1].cnp_rx_pkts; + cnps->prev[1].cnp_rx_bytes = tmp_counters[1].cnp_rx_bytes; + + dstat->prev[0].tx_pkts = roce_only_tmp[0].tx_pkts; + dstat->prev[0].tx_bytes = roce_only_tmp[0].tx_bytes; + dstat->prev[0].rx_pkts = roce_only_tmp[0].rx_pkts; + dstat->prev[0].rx_bytes = roce_only_tmp[0].rx_bytes; + + dstat->prev[1].tx_pkts = roce_only_tmp[1].tx_pkts; + dstat->prev[1].tx_bytes = roce_only_tmp[1].tx_bytes; + dstat->prev[1].rx_pkts = roce_only_tmp[1].rx_pkts; + dstat->prev[1].rx_bytes = roce_only_tmp[1].rx_bytes; + } else { + u64 byte_mask, pkts_mask; + u64 diff; + + byte_mask = bnxt_re_get_cfa_stat_mask(rdev->chip_ctx, + BYTE_MASK); + pkts_mask = bnxt_re_get_cfa_stat_mask(rdev->chip_ctx, + PKTS_MASK); + /* + * Calculate the number of cnp packets and use + * the value to calculate the CRC bytes. + * Multply pkts with 4 and add it to total bytes + */ + pkts = bnxt_re_stat_diff(tmp_counters[0].cnp_tx_pkts, + &cnps->prev[0].cnp_tx_pkts, + pkts_mask); + cnps->cur[0].cnp_tx_pkts += pkts; + diff = bnxt_re_stat_diff(tmp_counters[0].cnp_tx_bytes, + &cnps->prev[0].cnp_tx_bytes, + byte_mask); + bytes = diff + pkts * 4; + cnps->cur[0].cnp_tx_bytes += bytes; + pkts = bnxt_re_stat_diff(tmp_counters[0].cnp_rx_pkts, + &cnps->prev[0].cnp_rx_pkts, + pkts_mask); + cnps->cur[0].cnp_rx_pkts += pkts; + bytes = bnxt_re_stat_diff(tmp_counters[0].cnp_rx_bytes, + &cnps->prev[0].cnp_rx_bytes, + byte_mask); + cnps->cur[0].cnp_rx_bytes += bytes; + + /* + * Calculate the number of cnp packets and use + * the value to calculate the CRC bytes. + * Multply pkts with 4 and add it to total bytes + */ + pkts = bnxt_re_stat_diff(tmp_counters[1].cnp_tx_pkts, + &cnps->prev[1].cnp_tx_pkts, + pkts_mask); + cnps->cur[1].cnp_tx_pkts += pkts; + diff = bnxt_re_stat_diff(tmp_counters[1].cnp_tx_bytes, + &cnps->prev[1].cnp_tx_bytes, + byte_mask); + cnps->cur[1].cnp_tx_bytes += diff + pkts * 4; + pkts = bnxt_re_stat_diff(tmp_counters[1].cnp_rx_pkts, + &cnps->prev[1].cnp_rx_pkts, + pkts_mask); + cnps->cur[1].cnp_rx_pkts += pkts; + bytes = bnxt_re_stat_diff(tmp_counters[1].cnp_rx_bytes, + &cnps->prev[1].cnp_rx_bytes, + byte_mask); + cnps->cur[1].cnp_rx_bytes += bytes; + + pkts = bnxt_re_stat_diff(roce_only_tmp[0].tx_pkts, + &dstat->prev[0].tx_pkts, + pkts_mask); + dstat->cur[0].tx_pkts += pkts; + diff = bnxt_re_stat_diff(roce_only_tmp[0].tx_bytes, + &dstat->prev[0].tx_bytes, + byte_mask); + dstat->cur[0].tx_bytes += diff + pkts * 4; + pkts = bnxt_re_stat_diff(roce_only_tmp[0].rx_pkts, + &dstat->prev[0].rx_pkts, + pkts_mask); + dstat->cur[0].rx_pkts += pkts; + + bytes = bnxt_re_stat_diff(roce_only_tmp[0].rx_bytes, + &dstat->prev[0].rx_bytes, + byte_mask); + dstat->cur[0].rx_bytes += bytes; + pkts = bnxt_re_stat_diff(roce_only_tmp[1].tx_pkts, + &dstat->prev[1].tx_pkts, + pkts_mask); + dstat->cur[1].tx_pkts += pkts; + diff = bnxt_re_stat_diff(roce_only_tmp[1].tx_bytes, + &dstat->prev[1].tx_bytes, + byte_mask); + dstat->cur[1].tx_bytes += diff + pkts * 4; + pkts = bnxt_re_stat_diff(roce_only_tmp[1].rx_pkts, + &dstat->prev[1].rx_pkts, + pkts_mask); + dstat->cur[1].rx_pkts += pkts; + bytes = bnxt_re_stat_diff(roce_only_tmp[1].rx_bytes, + &dstat->prev[1].rx_bytes, + byte_mask); + dstat->cur[1].rx_bytes += bytes; + } +done: + return rc; +} + +static void bnxt_re_copy_ext_stats(struct bnxt_re_dev *rdev, + u8 indx, struct bnxt_qplib_ext_stat *s) +{ + struct bnxt_re_ext_roce_stats *e_errs; + struct bnxt_re_cnp_counters *cnp; + struct bnxt_re_ext_rstat *ext_d; + struct bnxt_re_ro_counters *ro; + + cnp = &rdev->stats.cnps.cur[indx]; + ro = &rdev->stats.dstat.cur[indx]; + ext_d = &rdev->stats.dstat.ext_rstat[indx]; + e_errs = &rdev->stats.dstat.e_errs; + + cnp->cnp_tx_pkts = s->tx_cnp; + cnp->cnp_rx_pkts = s->rx_cnp; + /* In bonding mode do not duplicate other stats */ + if (indx) + return; + cnp->ecn_marked = s->rx_ecn_marked; + + ro->tx_pkts = s->tx_roce_pkts; + ro->tx_bytes = s->tx_roce_bytes; + ro->rx_pkts = s->rx_roce_pkts; + ro->rx_bytes = s->rx_roce_bytes; + + ext_d->tx.atomic_req = s->tx_atomic_req; + ext_d->tx.read_req = s->tx_read_req; + ext_d->tx.read_resp = s->tx_read_res; + ext_d->tx.write_req = s->tx_write_req; + ext_d->tx.send_req = s->tx_send_req; + ext_d->rx.atomic_req = s->rx_atomic_req; + ext_d->rx.read_req = s->rx_read_req; + ext_d->rx.read_resp = s->rx_read_res; + ext_d->rx.write_req = s->rx_write_req; + ext_d->rx.send_req = s->rx_send_req; + ext_d->grx.rx_pkts = s->rx_roce_good_pkts; + ext_d->grx.rx_bytes = s->rx_roce_good_bytes; + ext_d->rx_dcn_payload_cut = s->rx_dcn_payload_cut; + ext_d->te_bypassed = s->te_bypassed; + e_errs->oob = s->rx_out_of_buffer; + e_errs->oos = s->rx_out_of_sequence; + e_errs->seq_err_naks_rcvd = s->seq_err_naks_rcvd; + e_errs->rnr_naks_rcvd = s->rnr_naks_rcvd; + e_errs->missing_resp = s->missing_resp; + e_errs->to_retransmits = s->to_retransmits; + e_errs->dup_req = s->dup_req; +} + +static int bnxt_re_get_ext_stat(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_ext_stat estat[2] = {{}, {}}; + struct bnxt_qplib_query_stats_info sinfo; + u32 fid; + int rc; + + fid = PCI_FUNC(rdev->en_dev->pdev->devfn); + /* Set default values for sinfo */ + sinfo.function_id = 0xFFFFFFFF; + sinfo.collection_id = 0xFF; + sinfo.vf_valid = false; + rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, &estat[0], &sinfo); + if (rc) + goto done; + bnxt_re_copy_ext_stats(rdev, 0, &estat[0]); + +done: + return rc; +} + +static void bnxt_re_copy_rstat(struct bnxt_re_rdata_counters *d, + struct ctx_hw_stats_ext *s, + bool is_thor) +{ + d->tx_ucast_pkts = le64_to_cpu(s->tx_ucast_pkts); + d->tx_mcast_pkts = le64_to_cpu(s->tx_mcast_pkts); + d->tx_bcast_pkts = le64_to_cpu(s->tx_bcast_pkts); + d->tx_discard_pkts = le64_to_cpu(s->tx_discard_pkts); + d->tx_error_pkts = le64_to_cpu(s->tx_error_pkts); + d->tx_ucast_bytes = le64_to_cpu(s->tx_ucast_bytes); + /* Add four bytes of CRC bytes per packet */ + d->tx_ucast_bytes += d->tx_ucast_pkts * 4; + d->tx_mcast_bytes = le64_to_cpu(s->tx_mcast_bytes); + d->tx_bcast_bytes = le64_to_cpu(s->tx_bcast_bytes); + d->rx_ucast_pkts = le64_to_cpu(s->rx_ucast_pkts); + d->rx_mcast_pkts = le64_to_cpu(s->rx_mcast_pkts); + d->rx_bcast_pkts = le64_to_cpu(s->rx_bcast_pkts); + d->rx_discard_pkts = le64_to_cpu(s->rx_discard_pkts); + d->rx_error_pkts = le64_to_cpu(s->rx_error_pkts); + d->rx_ucast_bytes = le64_to_cpu(s->rx_ucast_bytes); + d->rx_mcast_bytes = le64_to_cpu(s->rx_mcast_bytes); + d->rx_bcast_bytes = le64_to_cpu(s->rx_bcast_bytes); + if (is_thor) { + d->rx_agg_pkts = le64_to_cpu(s->rx_tpa_pkt); + d->rx_agg_bytes = le64_to_cpu(s->rx_tpa_bytes); + d->rx_agg_events = le64_to_cpu(s->rx_tpa_events); + d->rx_agg_aborts = le64_to_cpu(s->rx_tpa_errors); + } +} + +static void bnxt_re_get_roce_data_stats(struct bnxt_re_dev *rdev) +{ + bool is_thor = _is_chip_gen_p5_p7(rdev->chip_ctx); + struct bnxt_re_rdata_counters *rstat; + + rstat = &rdev->stats.dstat.rstat[0]; + bnxt_re_copy_rstat(rstat, rdev->qplib_res.hctx->stats.dma, is_thor); + +} + +int bnxt_re_get_device_stats(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_query_stats_info sinfo; + int rc = 0; + + /* Stats are in 1s cadence */ + if (test_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, &rdev->flags)) { + if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, + rdev->is_virtfn)) + rc = bnxt_re_get_ext_stat(rdev); + else + rc = bnxt_re_get_qos_stats(rdev); + + if (rc && rc != -ENOMEM) + clear_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, + &rdev->flags); + } + + if (test_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags)) { + bnxt_re_get_roce_data_stats(rdev); + + /* Set default values for sinfo */ + sinfo.function_id = 0xFFFFFFFF; + sinfo.collection_id = 0xFF; + sinfo.vf_valid = false; + rc = bnxt_qplib_get_roce_error_stats(&rdev->rcfw, + &rdev->stats.dstat.errs, + &sinfo); + if (rc && rc != -ENOMEM) + clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, + &rdev->flags); + } + + return rc; +} + +static const char * const bnxt_re_stat_descs[] = { + "link_state", + "max_qp", + "max_srq", + "max_cq", + "max_mr", + "max_mw", + "max_ah", + "max_pd", + "active_qp", + "active_rc_qp", + "active_ud_qp", + "active_srq", + "active_cq", + "active_mr", + "active_mw", + "active_ah", + "active_pd", + "qp_watermark", + "rc_qp_watermark", + "ud_qp_watermark", + "srq_watermark", + "cq_watermark", + "mr_watermark", + "mw_watermark", + "ah_watermark", + "pd_watermark", + "resize_cq_count", + "hw_retransmission", + "recoverable_errors", + "rx_pkts", + "rx_bytes", + "tx_pkts", + "tx_bytes", + "cnp_tx_pkts", + "cnp_tx_bytes", + "cnp_rx_pkts", + "cnp_rx_bytes", + "roce_only_rx_pkts", + "roce_only_rx_bytes", + "roce_only_tx_pkts", + "roce_only_tx_bytes", + "rx_roce_error_pkts", + "rx_roce_discard_pkts", + "tx_roce_error_pkts", + "tx_roce_discards_pkts", + "res_oob_drop_count", + "tx_atomic_req", + "rx_atomic_req", + "tx_read_req", + "tx_read_resp", + "rx_read_req", + "rx_read_resp", + "tx_write_req", + "rx_write_req", + "tx_send_req", + "rx_send_req", + "rx_good_pkts", + "rx_good_bytes", + "rx_dcn_payload_cut", + "te_bypassed", + "rx_ecn_marked_pkts", + "max_retry_exceeded", + "to_retransmits", + "seq_err_naks_rcvd", + "rnr_naks_rcvd", + "missing_resp", + "dup_reqs", + "unrecoverable_err", + "bad_resp_err", + "local_qp_op_err", + "local_protection_err", + "mem_mgmt_op_err", + "remote_invalid_req_err", + "remote_access_err", + "remote_op_err", + "res_exceed_max", + "res_length_mismatch", + "res_exceeds_wqe", + "res_opcode_err", + "res_rx_invalid_rkey", + "res_rx_domain_err", + "res_rx_no_perm", + "res_rx_range_err", + "res_tx_invalid_rkey", + "res_tx_domain_err", + "res_tx_no_perm", + "res_tx_range_err", + "res_irrq_oflow", + "res_unsup_opcode", + "res_unaligned_atomic", + "res_rem_inv_err", + "res_mem_error64", + "res_srq_err", + "res_cmp_err", + "res_invalid_dup_rkey", + "res_wqe_format_err", + "res_cq_load_err", + "res_srq_load_err", + "res_tx_pci_err", + "res_rx_pci_err", + "res_oos_drop_count", + "num_irq_started", + "num_irq_stopped", + "poll_in_intr_en", + "poll_in_intr_dis", + "cmdq_full_dbg_cnt", + "fw_service_prof_type_sup", + "dbq_int_recv", + "dbq_int_en", + "dbq_pacing_resched", + "dbq_pacing_complete", + "dbq_pacing_alerts", + "dbq_dbr_fifo_reg" + +}; + +static void bnxt_re_print_ext_stat(struct bnxt_re_dev *rdev, + struct rdma_hw_stats *stats) +{ + struct bnxt_re_cnp_counters *cnp; + struct bnxt_re_ext_rstat *ext_s; + + ext_s = &rdev->stats.dstat.ext_rstat[0]; + cnp = &rdev->stats.cnps.cur[0]; + + stats->value[BNXT_RE_TX_ATOMIC_REQ] = ext_s->tx.atomic_req; + stats->value[BNXT_RE_RX_ATOMIC_REQ] = ext_s->rx.atomic_req; + stats->value[BNXT_RE_TX_READ_REQ] = ext_s->tx.read_req; + stats->value[BNXT_RE_TX_READ_RESP] = ext_s->tx.read_resp; + stats->value[BNXT_RE_RX_READ_REQ] = ext_s->rx.read_req; + stats->value[BNXT_RE_RX_READ_RESP] = ext_s->rx.read_resp; + stats->value[BNXT_RE_TX_WRITE_REQ] = ext_s->tx.write_req; + stats->value[BNXT_RE_RX_WRITE_REQ] = ext_s->rx.write_req; + stats->value[BNXT_RE_TX_SEND_REQ] = ext_s->tx.send_req; + stats->value[BNXT_RE_RX_SEND_REQ] = ext_s->rx.send_req; + stats->value[BNXT_RE_RX_GOOD_PKTS] = ext_s->grx.rx_pkts; + stats->value[BNXT_RE_RX_GOOD_BYTES] = ext_s->grx.rx_bytes; + if (_is_chip_p7(rdev->chip_ctx)) { + stats->value[BNXT_RE_RX_DCN_PAYLOAD_CUT] = ext_s->rx_dcn_payload_cut; + stats->value[BNXT_RE_TE_BYPASSED] = ext_s->te_bypassed; + } + stats->value[BNXT_RE_RX_ECN_MARKED_PKTS] = cnp->ecn_marked; +} + +static void bnxt_re_print_roce_only_counters(struct bnxt_re_dev *rdev, + struct rdma_hw_stats *stats) +{ + struct bnxt_re_ro_counters *roce_only = &rdev->stats.dstat.cur[0]; + + stats->value[BNXT_RE_ROCE_ONLY_RX_PKTS] = roce_only->rx_pkts; + stats->value[BNXT_RE_ROCE_ONLY_RX_BYTES] = roce_only->rx_bytes; + stats->value[BNXT_RE_ROCE_ONLY_TX_PKTS] = roce_only->tx_pkts; + stats->value[BNXT_RE_ROCE_ONLY_TX_BYTES] = roce_only->tx_bytes; +} + +static void bnxt_re_print_normal_total_counters(struct bnxt_re_dev *rdev, + struct rdma_hw_stats *stats) +{ + struct bnxt_re_ro_counters *roce_only; + struct bnxt_re_cc_stat *cnps; + + cnps = &rdev->stats.cnps; + roce_only = &rdev->stats.dstat.cur[0]; + + stats->value[BNXT_RE_RX_PKTS] = cnps->cur[0].cnp_rx_pkts + roce_only->rx_pkts; + stats->value[BNXT_RE_RX_BYTES] = cnps->cur[0].cnp_rx_bytes + roce_only->rx_bytes; + stats->value[BNXT_RE_TX_PKTS] = cnps->cur[0].cnp_tx_pkts + roce_only->tx_pkts; + stats->value[BNXT_RE_TX_BYTES] = cnps->cur[0].cnp_tx_bytes + roce_only->tx_bytes; +} + +static void bnxt_re_print_normal_counters(struct bnxt_re_dev *rdev, + struct rdma_hw_stats *rstats) +{ + struct bnxt_re_rdata_counters *stats; + struct bnxt_re_cc_stat *cnps; + bool en_disp; + + stats = &rdev->stats.dstat.rstat[0]; + cnps = &rdev->stats.cnps; + en_disp = !_is_chip_gen_p5_p7(rdev->chip_ctx); + + bnxt_re_print_normal_total_counters(rdev, rstats); + if (!rdev->is_virtfn) { + rstats->value[BNXT_RE_CNP_TX_PKTS] = cnps->cur[0].cnp_tx_pkts; + if (en_disp) + rstats->value[BNXT_RE_CNP_TX_BYTES] = cnps->cur[0].cnp_tx_bytes; + rstats->value[BNXT_RE_CNP_RX_PKTS] = cnps->cur[0].cnp_rx_pkts; + if (en_disp) + rstats->value[BNXT_RE_CNP_RX_BYTES] = cnps->cur[0].cnp_rx_bytes; + } + /* Print RoCE only bytes.. CNP counters include RoCE packets also */ + bnxt_re_print_roce_only_counters(rdev, rstats); + + rstats->value[BNXT_RE_RX_ROCE_ERROR_PKTS] = stats ? stats->rx_error_pkts : 0; + rstats->value[BNXT_RE_RX_ROCE_DISCARD_PKTS] = stats ? stats->rx_discard_pkts : 0; + if (!en_disp) { + rstats->value[BNXT_RE_TX_ROCE_ERROR_PKTS] = stats ? stats->tx_error_pkts : 0; + rstats->value[BNXT_RE_TX_ROCE_DISCARDS_PKTS] = stats ? stats->tx_discard_pkts : 0; + } + + if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, + rdev->is_virtfn)) { + rstats->value[BNXT_RE_RES_OOB_DROP_COUNT] = rdev->stats.dstat.e_errs.oob; + bnxt_re_print_ext_stat(rdev, rstats); + } +} + +static void bnxt_re_copy_db_pacing_stats(struct bnxt_re_dev *rdev, + struct rdma_hw_stats *stats) +{ + struct bnxt_re_dbr_sw_stats *dbr_sw_stats = rdev->dbr_sw_stats; + + stats->value[BNXT_RE_DBQ_PACING_RESCHED] = dbr_sw_stats->dbq_pacing_resched; + stats->value[BNXT_RE_DBQ_PACING_CMPL] = dbr_sw_stats->dbq_pacing_complete; + stats->value[BNXT_RE_DBQ_PACING_ALERT] = dbr_sw_stats->dbq_pacing_alerts; + stats->value[BNXT_RE_DBQ_DBR_FIFO_REG] = readl_fbsd(rdev->en_dev->softc, + rdev->dbr_db_fifo_reg_off, 0); +} + +int bnxt_re_get_hw_stats(struct ib_device *ibdev, + struct rdma_hw_stats *stats, + u8 port, int index) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); + struct bnxt_re_ext_roce_stats *e_errs; + struct bnxt_re_rdata_counters *rstat; + struct bnxt_qplib_roce_stats *errs; + unsigned long tstamp_diff; + struct pci_dev *pdev; + int sched_msec; + int rc = 0; + + if (!port || !stats) + return -EINVAL; + + if (!rdev) + return -ENODEV; + + if (!__bnxt_re_is_rdev_valid(rdev)) { + return -ENODEV; + } + + pdev = rdev->en_dev->pdev; + errs = &rdev->stats.dstat.errs; + rstat = &rdev->stats.dstat.rstat[0]; + e_errs = &rdev->stats.dstat.e_errs; +#define BNXT_RE_STATS_CTX_UPDATE_TIMER 250 + sched_msec = BNXT_RE_STATS_CTX_UPDATE_TIMER; + tstamp_diff = jiffies - rdev->stats.read_tstamp; + if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) { + if (/* restrict_stats && */ tstamp_diff < msecs_to_jiffies(sched_msec)) + goto skip_query; + rc = bnxt_re_get_device_stats(rdev); + if (rc) + dev_err(rdev_to_dev(rdev), + "Failed to query device stats\n"); + rdev->stats.read_tstamp = jiffies; + } + + if (rdev->dbr_pacing) + bnxt_re_copy_db_pacing_stats(rdev, stats); + +skip_query: + + if (rdev->netdev) + stats->value[BNXT_RE_LINK_STATE] = bnxt_re_link_state(rdev); + stats->value[BNXT_RE_MAX_QP] = rdev->dev_attr->max_qp; + stats->value[BNXT_RE_MAX_SRQ] = rdev->dev_attr->max_srq; + stats->value[BNXT_RE_MAX_CQ] = rdev->dev_attr->max_cq; + stats->value[BNXT_RE_MAX_MR] = rdev->dev_attr->max_mr; + stats->value[BNXT_RE_MAX_MW] = rdev->dev_attr->max_mw; + stats->value[BNXT_RE_MAX_AH] = rdev->dev_attr->max_ah; + stats->value[BNXT_RE_MAX_PD] = rdev->dev_attr->max_pd; + stats->value[BNXT_RE_ACTIVE_QP] = atomic_read(&rdev->stats.rsors.qp_count); + stats->value[BNXT_RE_ACTIVE_RC_QP] = atomic_read(&rdev->stats.rsors.rc_qp_count); + stats->value[BNXT_RE_ACTIVE_UD_QP] = atomic_read(&rdev->stats.rsors.ud_qp_count); + stats->value[BNXT_RE_ACTIVE_SRQ] = atomic_read(&rdev->stats.rsors.srq_count); + stats->value[BNXT_RE_ACTIVE_CQ] = atomic_read(&rdev->stats.rsors.cq_count); + stats->value[BNXT_RE_ACTIVE_MR] = atomic_read(&rdev->stats.rsors.mr_count); + stats->value[BNXT_RE_ACTIVE_MW] = atomic_read(&rdev->stats.rsors.mw_count); + stats->value[BNXT_RE_ACTIVE_AH] = atomic_read(&rdev->stats.rsors.ah_count); + stats->value[BNXT_RE_ACTIVE_PD] = atomic_read(&rdev->stats.rsors.pd_count); + stats->value[BNXT_RE_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_qp_count); + stats->value[BNXT_RE_RC_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_rc_qp_count); + stats->value[BNXT_RE_UD_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_ud_qp_count); + stats->value[BNXT_RE_SRQ_WATERMARK] = atomic_read(&rdev->stats.rsors.max_srq_count); + stats->value[BNXT_RE_CQ_WATERMARK] = atomic_read(&rdev->stats.rsors.max_cq_count); + stats->value[BNXT_RE_MR_WATERMARK] = atomic_read(&rdev->stats.rsors.max_mr_count); + stats->value[BNXT_RE_MW_WATERMARK] = atomic_read(&rdev->stats.rsors.max_mw_count); + stats->value[BNXT_RE_AH_WATERMARK] = atomic_read(&rdev->stats.rsors.max_ah_count); + stats->value[BNXT_RE_PD_WATERMARK] = atomic_read(&rdev->stats.rsors.max_pd_count); + stats->value[BNXT_RE_RESIZE_CQ_COUNT] = atomic_read(&rdev->stats.rsors.resize_count); + stats->value[BNXT_RE_HW_RETRANSMISSION] = BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags) ? 1 : 0; + stats->value[BNXT_RE_RECOVERABLE_ERRORS] = rstat ? rstat->tx_bcast_pkts : 0; + + bnxt_re_print_normal_counters(rdev, stats); + + + stats->value[BNXT_RE_MAX_RETRY_EXCEEDED] = errs->max_retry_exceeded; + if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, + rdev->is_virtfn) && + _is_hw_retx_supported(rdev->dev_attr->dev_cap_flags)) { + stats->value[BNXT_RE_TO_RETRANSMITS] = e_errs->to_retransmits; + stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] = e_errs->seq_err_naks_rcvd; + stats->value[BNXT_RE_RNR_NAKS_RCVD] = e_errs->rnr_naks_rcvd; + stats->value[BNXT_RE_MISSING_RESP] = e_errs->missing_resp; + stats->value[BNXT_RE_DUP_REQS] = e_errs->dup_req; + } else { + stats->value[BNXT_RE_TO_RETRANSMITS] = errs->to_retransmits; + stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] = errs->seq_err_naks_rcvd; + stats->value[BNXT_RE_RNR_NAKS_RCVD] = errs->rnr_naks_rcvd; + stats->value[BNXT_RE_MISSING_RESP] = errs->missing_resp; + stats->value[BNXT_RE_DUP_REQS] = errs->dup_req; + } + + stats->value[BNXT_RE_UNRECOVERABLE_ERR] = errs->unrecoverable_err; + stats->value[BNXT_RE_BAD_RESP_ERR] = errs->bad_resp_err; + stats->value[BNXT_RE_LOCAL_QP_OP_ERR] = errs->local_qp_op_err; + stats->value[BNXT_RE_LOCAL_PROTECTION_ERR] = errs->local_protection_err; + stats->value[BNXT_RE_MEM_MGMT_OP_ERR] = errs->mem_mgmt_op_err; + stats->value[BNXT_RE_REMOTE_INVALID_REQ_ERR] = errs->remote_invalid_req_err; + stats->value[BNXT_RE_REMOTE_ACCESS_ERR] = errs->remote_access_err; + stats->value[BNXT_RE_REMOTE_OP_ERR] = errs->remote_op_err; + stats->value[BNXT_RE_RES_EXCEED_MAX] = errs->res_exceed_max; + stats->value[BNXT_RE_RES_LENGTH_MISMATCH] = errs->res_length_mismatch; + stats->value[BNXT_RE_RES_EXCEEDS_WQE] = errs->res_exceeds_wqe; + stats->value[BNXT_RE_RES_OPCODE_ERR] = errs->res_opcode_err; + stats->value[BNXT_RE_RES_RX_INVALID_RKEY] = errs->res_rx_invalid_rkey; + stats->value[BNXT_RE_RES_RX_DOMAIN_ERR] = errs->res_rx_domain_err; + stats->value[BNXT_RE_RES_RX_NO_PERM] = errs->res_rx_no_perm; + stats->value[BNXT_RE_RES_RX_RANGE_ERR] = errs->res_rx_range_err; + stats->value[BNXT_RE_RES_TX_INVALID_RKEY] = errs->res_tx_invalid_rkey; + stats->value[BNXT_RE_RES_TX_DOMAIN_ERR] = errs->res_tx_domain_err; + stats->value[BNXT_RE_RES_TX_NO_PERM] = errs->res_tx_no_perm; + stats->value[BNXT_RE_RES_TX_RANGE_ERR] = errs->res_tx_range_err; + stats->value[BNXT_RE_RES_IRRQ_OFLOW] = errs->res_irrq_oflow; + stats->value[BNXT_RE_RES_UNSUP_OPCODE] = errs->res_unsup_opcode; + stats->value[BNXT_RE_RES_UNALIGNED_ATOMIC] = errs->res_unaligned_atomic; + stats->value[BNXT_RE_RES_REM_INV_ERR] = errs->res_rem_inv_err; + stats->value[BNXT_RE_RES_MEM_ERROR64] = errs->res_mem_error; + stats->value[BNXT_RE_RES_SRQ_ERR] = errs->res_srq_err; + stats->value[BNXT_RE_RES_CMP_ERR] = errs->res_cmp_err; + stats->value[BNXT_RE_RES_INVALID_DUP_RKEY] = errs->res_invalid_dup_rkey; + stats->value[BNXT_RE_RES_WQE_FORMAT_ERR] = errs->res_wqe_format_err; + stats->value[BNXT_RE_RES_CQ_LOAD_ERR] = errs->res_cq_load_err; + stats->value[BNXT_RE_RES_SRQ_LOAD_ERR] = errs->res_srq_load_err; + stats->value[BNXT_RE_RES_TX_PCI_ERR] = errs->res_tx_pci_err; + stats->value[BNXT_RE_RES_RX_PCI_ERR] = errs->res_rx_pci_err; + + + if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, + rdev->is_virtfn)) { + stats->value[BNXT_RE_RES_OOS_DROP_COUNT] = e_errs->oos; + } else { + /* Display on function 0 as OOS counters are chip-wide */ + if (PCI_FUNC(pdev->devfn) == 0) + stats->value[BNXT_RE_RES_OOS_DROP_COUNT] = errs->res_oos_drop_count; + } + stats->value[BNXT_RE_NUM_IRQ_STARTED] = rdev->rcfw.num_irq_started; + stats->value[BNXT_RE_NUM_IRQ_STOPPED] = rdev->rcfw.num_irq_stopped; + stats->value[BNXT_RE_POLL_IN_INTR_EN] = rdev->rcfw.poll_in_intr_en; + stats->value[BNXT_RE_POLL_IN_INTR_DIS] = rdev->rcfw.poll_in_intr_dis; + stats->value[BNXT_RE_CMDQ_FULL_DBG_CNT] = rdev->rcfw.cmdq_full_dbg; + if (!rdev->is_virtfn) + stats->value[BNXT_RE_FW_SERVICE_PROF_TYPE_SUP] = is_qport_service_type_supported(rdev); + + return ARRAY_SIZE(bnxt_re_stat_descs); +} + +struct rdma_hw_stats *bnxt_re_alloc_hw_port_stats(struct ib_device *ibdev, + u8 port_num) +{ + return rdma_alloc_hw_stats_struct(bnxt_re_stat_descs, + ARRAY_SIZE(bnxt_re_stat_descs), + RDMA_HW_STATS_DEFAULT_LIFESPAN); +} diff --git a/sys/dev/bnxt/bnxt_re/stats.h b/sys/dev/bnxt/bnxt_re/stats.h new file mode 100644 index 000000000000..748d8165947b --- /dev/null +++ b/sys/dev/bnxt/bnxt_re/stats.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2015-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 AUTHOR 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 AUTHOR 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. + * + * Description: statistics related data structures + */ + +#ifndef __STATS_H__ +#define __STATS_H__ + +#define BNXT_RE_CFA_STAT_BYTES_MASK 0xFFFFFFFFF +#define BNXT_RE_CFA_STAT_PKTS_MASK 0xFFFFFFF +enum { + BYTE_MASK = 0, + PKTS_MASK = 1 +}; + +struct bnxt_re_cnp_counters { + u64 cnp_tx_pkts; + u64 cnp_tx_bytes; + u64 cnp_rx_pkts; + u64 cnp_rx_bytes; + u64 ecn_marked; +}; + +struct bnxt_re_ro_counters { + u64 tx_pkts; + u64 tx_bytes; + u64 rx_pkts; + u64 rx_bytes; +}; + +struct bnxt_re_flow_counters { + struct bnxt_re_ro_counters ro_stats; + struct bnxt_re_cnp_counters cnp_stats; +}; + +struct bnxt_re_ext_cntr { + u64 atomic_req; + u64 read_req; + u64 read_resp; + u64 write_req; + u64 send_req; +}; + +struct bnxt_re_ext_good { + u64 rx_pkts; + u64 rx_bytes; +}; + +struct bnxt_re_ext_rstat { + struct bnxt_re_ext_cntr tx; + struct bnxt_re_ext_cntr rx; + struct bnxt_re_ext_good grx; + u64 rx_dcn_payload_cut; + u64 te_bypassed; +}; + +struct bnxt_re_rdata_counters { + u64 tx_ucast_pkts; + u64 tx_mcast_pkts; + u64 tx_bcast_pkts; + u64 tx_discard_pkts; + u64 tx_error_pkts; + u64 tx_ucast_bytes; + u64 tx_mcast_bytes; + u64 tx_bcast_bytes; + u64 rx_ucast_pkts; + u64 rx_mcast_pkts; + u64 rx_bcast_pkts; + u64 rx_discard_pkts; + u64 rx_error_pkts; + u64 rx_ucast_bytes; + u64 rx_mcast_bytes; + u64 rx_bcast_bytes; + u64 rx_agg_pkts; + u64 rx_agg_bytes; + u64 rx_agg_events; + u64 rx_agg_aborts; +}; + +struct bnxt_re_cc_stat { + struct bnxt_re_cnp_counters prev[2]; + struct bnxt_re_cnp_counters cur[2]; + bool is_first; +}; + +struct bnxt_re_ext_roce_stats { + u64 oob; + u64 oos; + u64 seq_err_naks_rcvd; + u64 rnr_naks_rcvd; + u64 missing_resp; + u64 to_retransmits; + u64 dup_req; +}; + +struct bnxt_re_rstat { + struct bnxt_re_ro_counters prev[2]; + struct bnxt_re_ro_counters cur[2]; + struct bnxt_re_rdata_counters rstat[2]; + struct bnxt_re_ext_rstat ext_rstat[2]; + struct bnxt_re_ext_roce_stats e_errs; + struct bnxt_qplib_roce_stats errs; + unsigned long long prev_oob; +}; + +struct bnxt_re_res_cntrs { + atomic_t qp_count; + atomic_t rc_qp_count; + atomic_t ud_qp_count; + atomic_t cq_count; + atomic_t srq_count; + atomic_t mr_count; + atomic_t mw_count; + atomic_t ah_count; + atomic_t pd_count; + atomic_t resize_count; + atomic_t max_qp_count; + atomic_t max_rc_qp_count; + atomic_t max_ud_qp_count; + atomic_t max_cq_count; + atomic_t max_srq_count; + atomic_t max_mr_count; + atomic_t max_mw_count; + atomic_t max_ah_count; + atomic_t max_pd_count; +}; + +struct bnxt_re_device_stats { + struct bnxt_re_rstat dstat; + struct bnxt_re_res_cntrs rsors; + struct bnxt_re_cc_stat cnps; + unsigned long read_tstamp; + /* To be used in case to disable stats query from worker or change + * query interval. 0 means stats_query disabled. + */ + u32 stats_query_sec; + /* A free running counter to be used along with stats_query_sec to + * decide whether to issue the command to FW. + */ + u32 stats_query_counter; +}; + +static inline u64 bnxt_re_get_cfa_stat_mask(struct bnxt_qplib_chip_ctx *cctx, + bool type) +{ + u64 mask; + + if (type == BYTE_MASK) { + mask = BNXT_RE_CFA_STAT_BYTES_MASK; /* 36 bits */ + if (_is_chip_gen_p5_p7(cctx)) + mask >>= 0x01; /* 35 bits */ + } else { + mask = BNXT_RE_CFA_STAT_PKTS_MASK; /* 28 bits */ + if (_is_chip_gen_p5_p7(cctx)) + mask |= (0x10000000ULL); /* 29 bits */ + } + + return mask; +} + +static inline u64 bnxt_re_stat_diff(u64 cur, u64 *prev, u64 mask) +{ + u64 diff; + + if (!cur) + return 0; + diff = (cur - *prev) & mask; + if (diff) + *prev = cur; + return diff; +} + +static inline void bnxt_re_clear_rsors_stat(struct bnxt_re_res_cntrs *rsors) +{ + atomic_set(&rsors->qp_count, 0); + atomic_set(&rsors->cq_count, 0); + atomic_set(&rsors->srq_count, 0); + atomic_set(&rsors->mr_count, 0); + atomic_set(&rsors->mw_count, 0); + atomic_set(&rsors->ah_count, 0); + atomic_set(&rsors->pd_count, 0); + atomic_set(&rsors->resize_count, 0); + atomic_set(&rsors->max_qp_count, 0); + atomic_set(&rsors->max_cq_count, 0); + atomic_set(&rsors->max_srq_count, 0); + atomic_set(&rsors->max_mr_count, 0); + atomic_set(&rsors->max_mw_count, 0); + atomic_set(&rsors->max_ah_count, 0); + atomic_set(&rsors->max_pd_count, 0); + atomic_set(&rsors->max_rc_qp_count, 0); + atomic_set(&rsors->max_ud_qp_count, 0); +} + +enum bnxt_re_hw_stats { + BNXT_RE_LINK_STATE, + BNXT_RE_MAX_QP, + BNXT_RE_MAX_SRQ, + BNXT_RE_MAX_CQ, + BNXT_RE_MAX_MR, + BNXT_RE_MAX_MW, + BNXT_RE_MAX_AH, + BNXT_RE_MAX_PD, + BNXT_RE_ACTIVE_QP, + BNXT_RE_ACTIVE_RC_QP, + BNXT_RE_ACTIVE_UD_QP, + BNXT_RE_ACTIVE_SRQ, + BNXT_RE_ACTIVE_CQ, + BNXT_RE_ACTIVE_MR, + BNXT_RE_ACTIVE_MW, + BNXT_RE_ACTIVE_AH, + BNXT_RE_ACTIVE_PD, + BNXT_RE_QP_WATERMARK, + BNXT_RE_RC_QP_WATERMARK, + BNXT_RE_UD_QP_WATERMARK, + BNXT_RE_SRQ_WATERMARK, + BNXT_RE_CQ_WATERMARK, + BNXT_RE_MR_WATERMARK, + BNXT_RE_MW_WATERMARK, + BNXT_RE_AH_WATERMARK, + BNXT_RE_PD_WATERMARK, + BNXT_RE_RESIZE_CQ_COUNT, + BNXT_RE_HW_RETRANSMISSION, + BNXT_RE_RECOVERABLE_ERRORS, + BNXT_RE_RX_PKTS, + BNXT_RE_RX_BYTES, + BNXT_RE_TX_PKTS, + BNXT_RE_TX_BYTES, + BNXT_RE_CNP_TX_PKTS, + BNXT_RE_CNP_TX_BYTES, + BNXT_RE_CNP_RX_PKTS, + BNXT_RE_CNP_RX_BYTES, + BNXT_RE_ROCE_ONLY_RX_PKTS, + BNXT_RE_ROCE_ONLY_RX_BYTES, + BNXT_RE_ROCE_ONLY_TX_PKTS, + BNXT_RE_ROCE_ONLY_TX_BYTES, + BNXT_RE_RX_ROCE_ERROR_PKTS, + BNXT_RE_RX_ROCE_DISCARD_PKTS, + BNXT_RE_TX_ROCE_ERROR_PKTS, + BNXT_RE_TX_ROCE_DISCARDS_PKTS, + BNXT_RE_RES_OOB_DROP_COUNT, + BNXT_RE_TX_ATOMIC_REQ, + BNXT_RE_RX_ATOMIC_REQ, + BNXT_RE_TX_READ_REQ, + BNXT_RE_TX_READ_RESP, + BNXT_RE_RX_READ_REQ, + BNXT_RE_RX_READ_RESP, + BNXT_RE_TX_WRITE_REQ, + BNXT_RE_RX_WRITE_REQ, + BNXT_RE_TX_SEND_REQ, + BNXT_RE_RX_SEND_REQ, + BNXT_RE_RX_GOOD_PKTS, + BNXT_RE_RX_GOOD_BYTES, + BNXT_RE_RX_DCN_PAYLOAD_CUT, + BNXT_RE_TE_BYPASSED, + BNXT_RE_RX_ECN_MARKED_PKTS, + BNXT_RE_MAX_RETRY_EXCEEDED, + BNXT_RE_TO_RETRANSMITS, + BNXT_RE_SEQ_ERR_NAKS_RCVD, + BNXT_RE_RNR_NAKS_RCVD, + BNXT_RE_MISSING_RESP, + BNXT_RE_DUP_REQS, + BNXT_RE_UNRECOVERABLE_ERR, + BNXT_RE_BAD_RESP_ERR, + BNXT_RE_LOCAL_QP_OP_ERR, + BNXT_RE_LOCAL_PROTECTION_ERR, + BNXT_RE_MEM_MGMT_OP_ERR, + BNXT_RE_REMOTE_INVALID_REQ_ERR, + BNXT_RE_REMOTE_ACCESS_ERR, + BNXT_RE_REMOTE_OP_ERR, + BNXT_RE_RES_EXCEED_MAX, + BNXT_RE_RES_LENGTH_MISMATCH, + BNXT_RE_RES_EXCEEDS_WQE, + BNXT_RE_RES_OPCODE_ERR, + BNXT_RE_RES_RX_INVALID_RKEY, + BNXT_RE_RES_RX_DOMAIN_ERR, + BNXT_RE_RES_RX_NO_PERM, + BNXT_RE_RES_RX_RANGE_ERR, + BNXT_RE_RES_TX_INVALID_RKEY, + BNXT_RE_RES_TX_DOMAIN_ERR, + BNXT_RE_RES_TX_NO_PERM, + BNXT_RE_RES_TX_RANGE_ERR, + BNXT_RE_RES_IRRQ_OFLOW, + BNXT_RE_RES_UNSUP_OPCODE, + BNXT_RE_RES_UNALIGNED_ATOMIC, + BNXT_RE_RES_REM_INV_ERR, + BNXT_RE_RES_MEM_ERROR64, + BNXT_RE_RES_SRQ_ERR, + BNXT_RE_RES_CMP_ERR, + BNXT_RE_RES_INVALID_DUP_RKEY, + BNXT_RE_RES_WQE_FORMAT_ERR, + BNXT_RE_RES_CQ_LOAD_ERR, + BNXT_RE_RES_SRQ_LOAD_ERR, + BNXT_RE_RES_TX_PCI_ERR, + BNXT_RE_RES_RX_PCI_ERR, + BNXT_RE_RES_OOS_DROP_COUNT, + BNXT_RE_NUM_IRQ_STARTED, + BNXT_RE_NUM_IRQ_STOPPED, + BNXT_RE_POLL_IN_INTR_EN, + BNXT_RE_POLL_IN_INTR_DIS, + BNXT_RE_CMDQ_FULL_DBG_CNT, + BNXT_RE_FW_SERVICE_PROF_TYPE_SUP, + BNXT_RE_DBQ_INT_RECV, + BNXT_RE_DBQ_INT_EN, + BNXT_RE_DBQ_PACING_RESCHED, + BNXT_RE_DBQ_PACING_CMPL, + BNXT_RE_DBQ_PACING_ALERT, + BNXT_RE_DBQ_DBR_FIFO_REG, + BNXT_RE_DBQ_NUM_EXT_COUNTERS +}; + +#define BNXT_RE_NUM_STD_COUNTERS (BNXT_RE_OUT_OF_SEQ_ERR + 1) + +struct bnxt_re_stats { + struct bnxt_qplib_roce_stats errs; + struct bnxt_qplib_ext_stat ext_stat; +}; + +struct rdma_hw_stats *bnxt_re_alloc_hw_port_stats(struct ib_device *ibdev, + u8 port_num); +int bnxt_re_get_hw_stats(struct ib_device *ibdev, + struct rdma_hw_stats *stats, + u8 port, int index); +int bnxt_re_get_device_stats(struct bnxt_re_dev *rdev); +int bnxt_re_get_flow_stats_from_service_pf(struct bnxt_re_dev *rdev, + struct bnxt_re_flow_counters *stats, + struct bnxt_qplib_query_stats_info *sinfo); +int bnxt_re_get_qos_stats(struct bnxt_re_dev *rdev); +#endif /* __STATS_H__ */ |