diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h rename from sys/dev/bnxt/bnxt.h rename to sys/dev/bnxt/bnxt_en/bnxt.h --- a/sys/dev/bnxt/bnxt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -44,6 +44,7 @@ #include #include "hsi_struct_def.h" +#include "bnxt_dcb.h" /* PCI IDs */ #define BROADCOM_VENDOR_ID 0x14E4 @@ -359,9 +360,9 @@ 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 @@ 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_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 *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 @@ #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 @@ 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 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 @@ 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 @@ 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.h b/sys/dev/bnxt/bnxt_en/bnxt_dcb.h new file mode 100644 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.h @@ -0,0 +1,127 @@ +/*- + * 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 + +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } +#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ + __struct_group(/* no tag */, NAME, ATTRS, MEMBERS) + +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_en/bnxt_dcb.c b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c new file mode 100644 --- /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 +#include +#include + +#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; + + 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, int *num_inputs) +{ + bnxt_hwrm_get_dcbx_app(softc, app, num_inputs); + bnxt_hwrm_queue_dscp2pri_qcfg(softc, app, 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_hwrm.h b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h rename from sys/dev/bnxt/bnxt_hwrm.h rename to sys/dev/bnxt/bnxt_en/bnxt_hwrm.h --- a/sys/dev/bnxt/bnxt_hwrm.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.h @@ -45,7 +45,7 @@ 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_queue_qportcfg(struct bnxt_softc *softc, uint32_t path_dir); int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc); int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown); int bnxt_hwrm_func_qcaps(struct bnxt_softc *softc); @@ -128,7 +128,10 @@ 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_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c rename from sys/dev/bnxt/bnxt_hwrm.c rename to sys/dev/bnxt/bnxt_en/bnxt_hwrm.c --- a/sys/dev/bnxt/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c @@ -42,9 +42,6 @@ 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) @@ -97,7 +94,7 @@ return; } -static void +void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request, uint16_t req_type) { @@ -109,7 +106,7 @@ 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; @@ -222,7 +219,7 @@ return 0; } -static int +int hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) { int rc; @@ -234,13 +231,16 @@ } 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 +254,56 @@ 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; @@ -309,14 +336,14 @@ rc = -ENOMEM; goto ctx_err; } - ctx_pg = malloc(sizeof(*ctx_pg) * (softc->max_q + 1), + ctx_pg = malloc(sizeof(*ctx_pg) * (softc->rx_max_q + 1), M_DEVBUF, M_NOWAIT | M_ZERO); if (!ctx_pg) { free(ctx, M_DEVBUF); rc = -ENOMEM; goto ctx_err; } - for (i = 0; i < softc->max_q + 1; i++, ctx_pg++) + for (i = 0; i < softc->rx_max_q + 1; i++, ctx_pg++) ctx->tqm_mem[i] = ctx_pg; softc->ctx_mem = ctx; @@ -669,6 +696,7 @@ 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 +706,7 @@ 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); @@ -695,12 +724,33 @@ 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; @@ -766,6 +816,7 @@ 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 +826,70 @@ 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; + 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 +928,45 @@ 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; + 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) + if (rc) goto fail; 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); + + 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; fail: BNXT_HWRM_UNLOCK(softc); - return rc; + return rc; } int @@ -1282,48 +1409,48 @@ 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: + break; + case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX: if (!BNXT_CHIP_P5(softc)) break; cp_ring = &softc->rx_cp_rings[idx]; - req.stat_ctx_id = htole32(cp_ring->stats_ctx_id); + req.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: + 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; + 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: + 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.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; break; } @@ -1331,14 +1458,15 @@ 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)); @@ -2251,9 +2379,9 @@ (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; @@ -2366,6 +2494,15 @@ 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; @@ -2473,80 +2610,82 @@ 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: + /* + * TBD: * Check if Tx also needs to be done - * So far, Tx processing has been done in softirq contest - * + * 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; + 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) + int bmap_size) { struct hwrm_func_drv_rgtr_input req = {0}; + struct hwrm_func_drv_rgtr_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; bitstr_t *async_events_bmap; uint32_t *events; - int i; + int i, rc = 0; #define BNXT_MAX_NUM_ASYNC_EVENTS 256 async_events_bmap = bit_alloc(BNXT_MAX_NUM_ASYNC_EVENTS, M_DEVBUF, @@ -2578,15 +2717,22 @@ free(async_events_bmap, M_DEVBUF); - return hwrm_send_message(softc, &req, sizeof(req)); + rc = hwrm_send_message(softc, &req, sizeof(req)); + if (!rc) { + if (resp->flags & + le32toh(HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED)) + softc->fw_cap |= BNXT_FW_CAP_IF_CHANGE; + } + + 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_ioctl.h b/sys/dev/bnxt/bnxt_en/bnxt_ioctl.h rename from sys/dev/bnxt/bnxt_ioctl.h rename to sys/dev/bnxt/bnxt_en/bnxt_ioctl.h diff --git a/sys/dev/bnxt/bnxt_mgmt.h b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h rename from sys/dev/bnxt/bnxt_mgmt.h rename to sys/dev/bnxt/bnxt_en/bnxt_mgmt.h --- 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 { - 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_mgmt.c b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c rename from sys/dev/bnxt/bnxt_mgmt.c rename to sys/dev/bnxt/bnxt_en/bnxt_mgmt.c --- a/sys/dev/bnxt/bnxt_mgmt.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c @@ -95,6 +95,70 @@ return (error); } +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], + &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) @@ -345,9 +409,12 @@ 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_sysctl.h b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.h rename from sys/dev/bnxt/bnxt_sysctl.h rename to sys/dev/bnxt/bnxt_en/bnxt_sysctl.h --- 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_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_sysctl.c b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c rename from sys/dev/bnxt/bnxt_sysctl.c rename to sys/dev/bnxt/bnxt_en/bnxt_sysctl.c --- a/sys/dev/bnxt/bnxt_sysctl.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c @@ -105,6 +105,16 @@ 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, "dcb"); + if (!softc->dcb_oid) { + sysctl_ctx_free(&softc->dcb_ctx); + return ENOMEM; + } + return 0; } @@ -151,6 +161,14 @@ 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; } @@ -1460,34 +1478,38 @@ 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"); return 0; } @@ -1618,6 +1640,377 @@ return 0; } +static int +bnxt_dcb_dcbx_cap(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + int val; + int rc; + + if (softc == NULL) + return EBUSY; + + 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 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 bnxt_softc *softc, char *buf, + struct bnxt_dcb_app *app, int num) +{ + uint32_t i; + + if (!num) { + buf += sprintf(buf, " None"); + return; + } + + buf += sprintf(buf, "\n"); + for (i = 0; i < num; i++) { + buf += sprintf(buf, "\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 bnxt_dcb_app app[128] = {0}; + struct bnxt_softc *softc = arg1; + int rc, num_inputs = 0; + char *buf; + + if (softc == NULL) + return EBUSY; + +#define BNXT_APP_TLV_STR_LEN 4096 + buf = malloc(BNXT_APP_TLV_STR_LEN, M_DEVBUF, M_NOWAIT | M_ZERO); + if (!buf) + return ENOMEM; + + bnxt_dcb_ieee_listapp(softc, app, &num_inputs); + bnxt_app_tlv_get_string(softc, buf, app, num_inputs); + + rc = sysctl_handle_string(oidp, buf, BNXT_APP_TLV_STR_LEN, req); + if (rc || req->newptr == NULL) + goto end; + +end: + free(buf, M_DEVBUF); + 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; + + if (softc == NULL) + return EBUSY; + + 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; + + if (softc == NULL) + return EBUSY; + + 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]; + + if (softc == NULL) + return EBUSY; + + 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]; + + if (softc == NULL) + return EBUSY; + + 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 or Disable LRO: 0 / 1"); + + 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_txrx.c b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c rename from sys/dev/bnxt/bnxt_txrx.c rename to sys/dev/bnxt/bnxt_en/bnxt_txrx.c diff --git a/sys/dev/bnxt/convert_hsi.pl b/sys/dev/bnxt/bnxt_en/convert_hsi.pl rename from sys/dev/bnxt/convert_hsi.pl rename to 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 rename from sys/dev/bnxt/hsi_struct_def.h rename to sys/dev/bnxt/bnxt_en/hsi_struct_def.h diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c rename from sys/dev/bnxt/if_bnxt.c rename to sys/dev/bnxt/bnxt_en/if_bnxt.c --- a/sys/dev/bnxt/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -965,7 +965,7 @@ return; if (ctx->tqm_mem[0]) { - for (i = 0; i < softc->max_q + 1; i++) { + for (i = 0; i < softc->rx_max_q + 1; i++) { if (!ctx->tqm_mem[i]) continue; bnxt_free_ctx_pg_tbls(softc, ctx->tqm_mem[i]); @@ -1078,7 +1078,7 @@ 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++) { + for (i = 0; i < softc->rx_max_q + 1; i++) { ctx_pg = ctx->tqm_mem[i]; ctx_pg->entries = entries; mem_size = ctx->tqm_entry_size * entries; @@ -1261,6 +1261,23 @@ 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); +} + /* Device setup and teardown */ static int bnxt_attach_pre(if_ctx_t ctx) @@ -1361,12 +1378,10 @@ softc->flags |= BNXT_FLAG_TPA; - /* No TPA for Thor A0 */ if (BNXT_CHIP_P5(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)) softc->flags &= ~BNXT_FLAG_TPA; @@ -1414,11 +1429,24 @@ } /* 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)); + } if (softc->hwrm_spec_code >= 0x10803) { rc = bnxt_alloc_ctx_mem(softc); @@ -1581,6 +1609,10 @@ if (rc) goto failed; + rc = bnxt_create_dcb_sysctls(softc); + if (rc) + goto failed; + /* Initialize the vlan list */ SLIST_INIT(&softc->vnic_info.vlan_tags); softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; @@ -1856,7 +1888,6 @@ softc->is_dev_init = true; bnxt_clear_ids(softc); - // TBD -- Check if it is needed for Thor as well if (BNXT_CHIP_P5(softc)) goto skip_def_cp_ring; /* Allocate the default completion ring */ @@ -2001,6 +2032,7 @@ bnxt_get_port_module_status(softc); bnxt_media_status(softc->ctx, &ifmr); bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); + bnxt_dcb_init(softc); return; fail: @@ -2015,6 +2047,7 @@ struct bnxt_softc *softc = iflib_get_softc(ctx); softc->is_dev_init = false; + bnxt_dcb_free(softc); bnxt_do_disable_intr(&softc->def_cp_ring); bnxt_func_reset(softc); bnxt_clear_ids(softc); @@ -2985,6 +3018,7 @@ 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, diff --git a/sys/modules/bnxt/Makefile b/sys/modules/bnxt/bnxt_en/Makefile rename from sys/modules/bnxt/Makefile rename to sys/modules/bnxt/bnxt_en/Makefile --- a/sys/modules/bnxt/Makefile +++ b/sys/modules/bnxt/bnxt_en/Makefile @@ -1,5 +1,5 @@ -.PATH: ${SRCTOP}/sys/dev/bnxt +.PATH: ${SRCTOP}/sys/dev/bnxt/bnxt_en KMOD = if_bnxt SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h @@ -8,7 +8,9 @@ SRCS += bnxt_hwrm.c SRCS += bnxt_sysctl.c SRCS += bnxt_mgmt.c +SRCS += bnxt_dcb.c bnxt_dcb.h CFLAGS+= -DIFLIB +CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include .include