The branch main has been updated by ssaxena:

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

commit 35b53f8c989f62286aad075ef2e97bba358144f8
Author:     Chandrakanth patil <[email protected]>
AuthorDate: 2024-04-28 09:24:30 +0000
Commit:     Sumit Saxena <[email protected]>
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 +-
 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 ***

Reply via email to