Re: git: 35b53f8c989f - main - bnxt_en: Add PFC, ETS & App TLVs protocols support

From: <tuexen_at_freebsd.org>
Date: Tue, 28 May 2024 11:03:09 UTC
> On 28. May 2024, at 12:17, Sumit Saxena <ssaxena@FreeBSD.org> wrote:
> 
> The branch main has been updated by ssaxena:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=35b53f8c989f62286aad075ef2e97bba358144f8
> 
> commit 35b53f8c989f62286aad075ef2e97bba358144f8
> Author:     Chandrakanth patil <chandrakanth.patil@broadcom.com>
> AuthorDate: 2024-04-28 09:24:30 +0000
> Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
> CommitDate: 2024-05-28 10:15:29 +0000
> 
>   bnxt_en: Add PFC, ETS & App TLVs protocols support
> 
>   Created new directory "bnxt_en" in /dev/bnxt and /modules/bnxt
>   and moved source files and Makefile into respective directory.
> 
>   ETS support:
> 
>      - Added new files bnxt_dcb.c & bnxt_dcb.h
>      - Added sysctl node 'dcb' and created handlers 'ets' and
>        'dcbx_cap'
>      - Add logic to validate user input and configure ETS in
>        the firmware
>      - Updated makefile to include bnxt_dcb.c & bnxt_dcb.h
> 
>   PFC support:
> 
>      - Created sysctl handlers 'pfc' under node 'dcb'
>      - Added logic to validate user input and configure PFC in
>        the firmware.
> 
>   App TLV support:
> 
>      - Created 3 new sysctl handlers under node 'dcb'
>          - set_apptlv (write only): Sets a specified TLV
>          - del_apptlv (write only): Deletes a specified TLV
>          - list_apptlv (read only): Lists all APP TLVs configured
>      - Added logic to validate user input and configure APP TLVs
>        in the firmware.
> 
>   Added Below DCB ops for management interface:
> 
>      - Set PFC, Get PFC, Set ETS, Get ETS, Add App_TLV, Del App_TLV
>        Lst App_TLV
> 
>   Reviewed by:            imp
>   Approved by:            imp
>   Differential revision:  https://reviews.freebsd.org/D45005
> ---
> sys/dev/bnxt/{ => bnxt_en}/bnxt.h           | 196 +++++--
> sys/dev/bnxt/bnxt_en/bnxt_dcb.c             | 861 ++++++++++++++++++++++++++++
> sys/dev/bnxt/bnxt_en/bnxt_dcb.h             | 127 ++++
> sys/dev/bnxt/{ => bnxt_en}/bnxt_hwrm.c      | 408 ++++++++-----
> sys/dev/bnxt/{ => bnxt_en}/bnxt_hwrm.h      |   7 +-
> sys/dev/bnxt/{ => bnxt_en}/bnxt_ioctl.h     |   0
> sys/dev/bnxt/{ => bnxt_en}/bnxt_mgmt.c      |  69 ++-
> sys/dev/bnxt/{ => bnxt_en}/bnxt_mgmt.h      |  31 +-
> sys/dev/bnxt/{ => bnxt_en}/bnxt_sysctl.c    | 429 +++++++++++++-
> sys/dev/bnxt/{ => bnxt_en}/bnxt_sysctl.h    |   2 +
> sys/dev/bnxt/{ => bnxt_en}/bnxt_txrx.c      |   0
> sys/dev/bnxt/{ => bnxt_en}/convert_hsi.pl   |   0
> sys/dev/bnxt/{ => bnxt_en}/hsi_struct_def.h |   0
> sys/dev/bnxt/{ => bnxt_en}/if_bnxt.c        |  48 +-
> sys/modules/bnxt/{ => bnxt_en}/Makefile     |   4 +-
Don't we need some Makefile in sys/modules/bnxt? For me this breaks the build.

Best regards
Michael
> 15 files changed, 1978 insertions(+), 204 deletions(-)
> 
> diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
> similarity index 78%
> rename from sys/dev/bnxt/bnxt.h
> rename to sys/dev/bnxt/bnxt_en/bnxt.h
> index 0547bae91e09..e68943fd6286 100644
> --- a/sys/dev/bnxt/bnxt.h
> +++ b/sys/dev/bnxt/bnxt_en/bnxt.h
> @@ -44,6 +44,7 @@
> #include <net/iflib.h>
> 
> #include "hsi_struct_def.h"
> +#include "bnxt_dcb.h"
> 
> /* PCI IDs */
> #define BROADCOM_VENDOR_ID 0x14E4
> @@ -359,9 +360,9 @@ enum bnxt_cp_type {
> BNXT_SHARED
> };
> 
> -struct bnxt_cos_queue {
> - uint8_t id;
> - uint8_t profile;
> +struct bnxt_queue_info {
> + uint8_t queue_id;
> + uint8_t queue_profile;
> };
> 
> struct bnxt_func_info {
> @@ -532,6 +533,13 @@ struct bnxt_ver_info {
> 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;
> @@ -644,38 +652,52 @@ struct bnxt_ctx_mem_info {
> };
> 
> 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;
> + 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
> };
> 
> -#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)
> +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)
> 
> @@ -684,6 +706,10 @@ struct bnxt_softc_list {
> struct bnxt_softc *softc;
> };
> 
> +#ifndef BIT_ULL
> +#define BIT_ULL(nr) (1ULL << (nr))
> +#endif
> +
> struct bnxt_softc {
> device_t dev;
> if_ctx_t ctx;
> @@ -710,6 +736,8 @@ struct bnxt_softc {
> #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
> uint32_t flags;
> #define BNXT_STATE_LINK_CHANGE  (0)
> #define BNXT_STATE_MAX (BNXT_STATE_LINK_CHANGE + 1)
> @@ -732,13 +760,23 @@ struct bnxt_softc {
> uint16_t hwrm_max_ext_req_len;
> uint32_t hwrm_spec_code;
> 
> -#define BNXT_MAX_COS_QUEUE 8
> +#define BNXT_MAX_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;
> + 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;
> @@ -782,6 +820,8 @@ struct bnxt_softc {
> 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;
> @@ -796,13 +836,78 @@ struct bnxt_softc {
> uint16_t                tx_coal_usecs;
> uint16_t                tx_coal_usecs_irq;
> uint16_t                tx_coal_frames;
> - uint16_t                tx_coal_frames_irq;
> + 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_filter_info {
> @@ -843,6 +948,17 @@ struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn,
> 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, int *num_inputs);
> 
> #endif /* _BNXT_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..e1e0581d3c24
> --- /dev/null
> +++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c
> @@ -0,0 +1,861 @@
> +/*-
> + * 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, 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; 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, 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; 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;
> *** 1821 LINES SKIPPED ***