Re: git: 35b53f8c989f - main - bnxt_en: Add PFC, ETS & App TLVs protocols support
- In reply to: Sumit Saxena : "git: 35b53f8c989f - main - bnxt_en: Add PFC, ETS & App TLVs protocols support"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 28 May 2024 11:03:09 UTC
> On 28. May 2024, at 12:17, Sumit Saxena <ssaxena@FreeBSD.org> wrote: > > The branch main has been updated by ssaxena: > > URL: https://cgit.FreeBSD.org/src/commit/?id=35b53f8c989f62286aad075ef2e97bba358144f8 > > commit 35b53f8c989f62286aad075ef2e97bba358144f8 > Author: Chandrakanth patil <chandrakanth.patil@broadcom.com> > AuthorDate: 2024-04-28 09:24:30 +0000 > Commit: Sumit Saxena <ssaxena@FreeBSD.org> > CommitDate: 2024-05-28 10:15:29 +0000 > > bnxt_en: Add PFC, ETS & App TLVs protocols support > > Created new directory "bnxt_en" in /dev/bnxt and /modules/bnxt > and moved source files and Makefile into respective directory. > > ETS support: > > - Added new files bnxt_dcb.c & bnxt_dcb.h > - Added sysctl node 'dcb' and created handlers 'ets' and > 'dcbx_cap' > - Add logic to validate user input and configure ETS in > the firmware > - Updated makefile to include bnxt_dcb.c & bnxt_dcb.h > > PFC support: > > - Created sysctl handlers 'pfc' under node 'dcb' > - Added logic to validate user input and configure PFC in > the firmware. > > App TLV support: > > - Created 3 new sysctl handlers under node 'dcb' > - set_apptlv (write only): Sets a specified TLV > - del_apptlv (write only): Deletes a specified TLV > - list_apptlv (read only): Lists all APP TLVs configured > - Added logic to validate user input and configure APP TLVs > in the firmware. > > Added Below DCB ops for management interface: > > - Set PFC, Get PFC, Set ETS, Get ETS, Add App_TLV, Del App_TLV > Lst App_TLV > > Reviewed by: imp > Approved by: imp > Differential revision: https://reviews.freebsd.org/D45005 > --- > sys/dev/bnxt/{ => bnxt_en}/bnxt.h | 196 +++++-- > sys/dev/bnxt/bnxt_en/bnxt_dcb.c | 861 ++++++++++++++++++++++++++++ > sys/dev/bnxt/bnxt_en/bnxt_dcb.h | 127 ++++ > sys/dev/bnxt/{ => bnxt_en}/bnxt_hwrm.c | 408 ++++++++----- > sys/dev/bnxt/{ => bnxt_en}/bnxt_hwrm.h | 7 +- > sys/dev/bnxt/{ => bnxt_en}/bnxt_ioctl.h | 0 > sys/dev/bnxt/{ => bnxt_en}/bnxt_mgmt.c | 69 ++- > sys/dev/bnxt/{ => bnxt_en}/bnxt_mgmt.h | 31 +- > sys/dev/bnxt/{ => bnxt_en}/bnxt_sysctl.c | 429 +++++++++++++- > sys/dev/bnxt/{ => bnxt_en}/bnxt_sysctl.h | 2 + > sys/dev/bnxt/{ => bnxt_en}/bnxt_txrx.c | 0 > sys/dev/bnxt/{ => bnxt_en}/convert_hsi.pl | 0 > sys/dev/bnxt/{ => bnxt_en}/hsi_struct_def.h | 0 > sys/dev/bnxt/{ => bnxt_en}/if_bnxt.c | 48 +- > sys/modules/bnxt/{ => bnxt_en}/Makefile | 4 +- Don't we need some Makefile in sys/modules/bnxt? For me this breaks the build. Best regards Michael > 15 files changed, 1978 insertions(+), 204 deletions(-) > > diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h > similarity index 78% > rename from sys/dev/bnxt/bnxt.h > rename to sys/dev/bnxt/bnxt_en/bnxt.h > index 0547bae91e09..e68943fd6286 100644 > --- a/sys/dev/bnxt/bnxt.h > +++ b/sys/dev/bnxt/bnxt_en/bnxt.h > @@ -44,6 +44,7 @@ > #include <net/iflib.h> > > #include "hsi_struct_def.h" > +#include "bnxt_dcb.h" > > /* PCI IDs */ > #define BROADCOM_VENDOR_ID 0x14E4 > @@ -359,9 +360,9 @@ enum bnxt_cp_type { > BNXT_SHARED > }; > > -struct bnxt_cos_queue { > - uint8_t id; > - uint8_t profile; > +struct bnxt_queue_info { > + uint8_t queue_id; > + uint8_t queue_profile; > }; > > struct bnxt_func_info { > @@ -532,6 +533,13 @@ struct bnxt_ver_info { > uint8_t hwrm_min_major; > uint8_t hwrm_min_minor; > uint8_t hwrm_min_update; > + uint64_t fw_ver_code; > +#define BNXT_FW_VER_CODE(maj, min, bld, rsv) \ > + ((uint64_t)(maj) << 48 | (uint64_t)(min) << 32 | (uint64_t)(bld) << 16 | (rsv)) > +#define BNXT_FW_MAJ(softc) ((softc)->ver_info->fw_ver_code >> 48) > +#define BNXT_FW_MIN(softc) (((softc)->ver_info->fw_ver_code >> 32) & 0xffff) > +#define BNXT_FW_BLD(softc) (((softc)->ver_info->fw_ver_code >> 16) & 0xffff) > +#define BNXT_FW_RSV(softc) (((softc)->ver_info->fw_ver_code) & 0xffff) > > struct sysctl_ctx_list ver_ctx; > struct sysctl_oid *ver_oid; > @@ -644,38 +652,52 @@ struct bnxt_ctx_mem_info { > }; > > struct bnxt_hw_resc { > - uint16_t min_rsscos_ctxs; > - uint16_t max_rsscos_ctxs; > - uint16_t min_cp_rings; > - uint16_t max_cp_rings; > - uint16_t resv_cp_rings; > - uint16_t min_tx_rings; > - uint16_t max_tx_rings; > - uint16_t resv_tx_rings; > - uint16_t max_tx_sch_inputs; > - uint16_t min_rx_rings; > - uint16_t max_rx_rings; > - uint16_t resv_rx_rings; > - uint16_t min_hw_ring_grps; > - uint16_t max_hw_ring_grps; > - uint16_t resv_hw_ring_grps; > - uint16_t min_l2_ctxs; > - uint16_t max_l2_ctxs; > - uint16_t min_vnics; > - uint16_t max_vnics; > - uint16_t resv_vnics; > - uint16_t min_stat_ctxs; > - uint16_t max_stat_ctxs; > - uint16_t resv_stat_ctxs; > - uint16_t max_nqs; > - uint16_t max_irqs; > - uint16_t resv_irqs; > + uint16_t min_rsscos_ctxs; > + uint16_t max_rsscos_ctxs; > + uint16_t min_cp_rings; > + uint16_t max_cp_rings; > + uint16_t resv_cp_rings; > + uint16_t min_tx_rings; > + uint16_t max_tx_rings; > + uint16_t resv_tx_rings; > + uint16_t max_tx_sch_inputs; > + uint16_t min_rx_rings; > + uint16_t max_rx_rings; > + uint16_t resv_rx_rings; > + uint16_t min_hw_ring_grps; > + uint16_t max_hw_ring_grps; > + uint16_t resv_hw_ring_grps; > + uint16_t min_l2_ctxs; > + uint16_t max_l2_ctxs; > + uint16_t min_vnics; > + uint16_t max_vnics; > + uint16_t resv_vnics; > + uint16_t min_stat_ctxs; > + uint16_t max_stat_ctxs; > + uint16_t resv_stat_ctxs; > + uint16_t max_nqs; > + uint16_t max_irqs; > + uint16_t resv_irqs; > +} > + > +enum bnxt_type_ets { > + BNXT_TYPE_ETS_TSA = 0, > + BNXT_TYPE_ETS_PRI2TC, > + BNXT_TYPE_ETS_TCBW, > + BNXT_TYPE_ETS_MAX > }; > > -#define BNXT_LLQ(q_profile) \ > - ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE) > -#define BNXT_CNPQ(q_profile) \ > - ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP) > +static const char *const BNXT_ETS_TYPE_STR[] = { > + "tsa", > + "pri2tc", > + "tcbw", > +}; > + > +static const char *const BNXT_ETS_HELP_STR[] = { > + "X is 1 (strict), 0 (ets)", > + "TC values for pri 0 to 7", > + "TC BW values for pri 0 to 7, Sum should be 100", > +}; > > #define BNXT_HWRM_MAX_REQ_LEN (softc->hwrm_max_req_len) > > @@ -684,6 +706,10 @@ struct bnxt_softc_list { > struct bnxt_softc *softc; > }; > > +#ifndef BIT_ULL > +#define BIT_ULL(nr) (1ULL << (nr)) > +#endif > + > struct bnxt_softc { > device_t dev; > if_ctx_t ctx; > @@ -710,6 +736,8 @@ struct bnxt_softc { > #define BNXT_FLAG_CHIP_P5 0x0020 > #define BNXT_FLAG_TPA 0x0040 > #define BNXT_FLAG_FW_CAP_EXT_STATS 0x0080 > +#define BNXT_FLAG_MULTI_HOST 0x0100 > +#define BNXT_FLAG_MULTI_ROOT 0x0200 > uint32_t flags; > #define BNXT_STATE_LINK_CHANGE (0) > #define BNXT_STATE_MAX (BNXT_STATE_LINK_CHANGE + 1) > @@ -732,13 +760,23 @@ struct bnxt_softc { > uint16_t hwrm_max_ext_req_len; > uint32_t hwrm_spec_code; > > -#define BNXT_MAX_COS_QUEUE 8 > +#define BNXT_MAX_QUEUE 8 > uint8_t max_tc; > - uint8_t max_lltc; /* lossless TCs */ > - struct bnxt_cos_queue q_info[BNXT_MAX_COS_QUEUE]; > - uint8_t tc_to_qidx[BNXT_MAX_COS_QUEUE]; > - uint8_t q_ids[BNXT_MAX_COS_QUEUE]; > - uint8_t max_q; > + uint8_t max_lltc; > + struct bnxt_queue_info tx_q_info[BNXT_MAX_QUEUE]; > + struct bnxt_queue_info rx_q_info[BNXT_MAX_QUEUE]; > + uint8_t tc_to_qidx[BNXT_MAX_QUEUE]; > + uint8_t tx_q_ids[BNXT_MAX_QUEUE]; > + uint8_t rx_q_ids[BNXT_MAX_QUEUE]; > + uint8_t tx_max_q; > + uint8_t rx_max_q; > + uint8_t is_asym_q; > + > + struct bnxt_ieee_ets *ieee_ets; > + struct bnxt_ieee_pfc *ieee_pfc; > + uint8_t dcbx_cap; > + uint8_t default_pri; > + uint8_t max_dscp_value; > > uint64_t admin_ticks; > struct iflib_dma_info hw_rx_port_stats; > @@ -782,6 +820,8 @@ struct bnxt_softc { > struct sysctl_oid *hw_lro_oid; > struct sysctl_ctx_list flow_ctrl_ctx; > struct sysctl_oid *flow_ctrl_oid; > + struct sysctl_ctx_list dcb_ctx; > + struct sysctl_oid *dcb_oid; > > struct bnxt_ver_info *ver_info; > struct bnxt_nvram_info *nvm_info; > @@ -796,13 +836,78 @@ struct bnxt_softc { > uint16_t tx_coal_usecs; > uint16_t tx_coal_usecs_irq; > uint16_t tx_coal_frames; > - uint16_t tx_coal_frames_irq; > + uint16_t tx_coal_frames_irq; > > #define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2) > #define BNXT_DEF_STATS_COAL_TICKS 1000000 > #define BNXT_MIN_STATS_COAL_TICKS 250000 > #define BNXT_MAX_STATS_COAL_TICKS 1000000 > > + uint64_t fw_cap; > + #define BNXT_FW_CAP_SHORT_CMD BIT_ULL(0) > + #define BNXT_FW_CAP_LLDP_AGENT BIT_ULL(1) > + #define BNXT_FW_CAP_DCBX_AGENT BIT_ULL(2) > + #define BNXT_FW_CAP_NEW_RM BIT_ULL(3) > + #define BNXT_FW_CAP_IF_CHANGE BIT_ULL(4) > + #define BNXT_FW_CAP_LINK_ADMIN BIT_ULL(5) > + #define BNXT_FW_CAP_VF_RES_MIN_GUARANTEED BIT_ULL(6) > + #define BNXT_FW_CAP_KONG_MB_CHNL BIT_ULL(7) > + #define BNXT_FW_CAP_ADMIN_MTU BIT_ULL(8) > + #define BNXT_FW_CAP_ADMIN_PF BIT_ULL(9) > + #define BNXT_FW_CAP_OVS_64BIT_HANDLE BIT_ULL(10) > + #define BNXT_FW_CAP_TRUSTED_VF BIT_ULL(11) > + #define BNXT_FW_CAP_VF_VNIC_NOTIFY BIT_ULL(12) > + #define BNXT_FW_CAP_ERROR_RECOVERY BIT_ULL(13) > + #define BNXT_FW_CAP_PKG_VER BIT_ULL(14) > + #define BNXT_FW_CAP_CFA_ADV_FLOW BIT_ULL(15) > + #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2 BIT_ULL(16) > + #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED BIT_ULL(17) > + #define BNXT_FW_CAP_EXT_STATS_SUPPORTED BIT_ULL(18) > + #define BNXT_FW_CAP_SECURE_MODE BIT_ULL(19) > + #define BNXT_FW_CAP_ERR_RECOVER_RELOAD BIT_ULL(20) > + #define BNXT_FW_CAP_HOT_RESET BIT_ULL(21) > + #define BNXT_FW_CAP_CRASHDUMP BIT_ULL(23) > + #define BNXT_FW_CAP_VLAN_RX_STRIP BIT_ULL(24) > + #define BNXT_FW_CAP_VLAN_TX_INSERT BIT_ULL(25) > + #define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED BIT_ULL(26) > + #define BNXT_FW_CAP_CFA_EEM BIT_ULL(27) > + #define BNXT_FW_CAP_DBG_QCAPS BIT_ULL(29) > + #define BNXT_FW_CAP_RING_MONITOR BIT_ULL(30) > + #define BNXT_FW_CAP_ECN_STATS BIT_ULL(31) > + #define BNXT_FW_CAP_TRUFLOW BIT_ULL(32) > + #define BNXT_FW_CAP_VF_CFG_FOR_PF BIT_ULL(33) > + #define BNXT_FW_CAP_PTP_PPS BIT_ULL(34) > + #define BNXT_FW_CAP_HOT_RESET_IF BIT_ULL(35) > + #define BNXT_FW_CAP_LIVEPATCH BIT_ULL(36) > + #define BNXT_FW_CAP_NPAR_1_2 BIT_ULL(37) > + #define BNXT_FW_CAP_RSS_HASH_TYPE_DELTA BIT_ULL(38) > + #define BNXT_FW_CAP_PTP_RTC BIT_ULL(39) > + #define BNXT_FW_CAP_TRUFLOW_EN BIT_ULL(40) > + #define BNXT_TRUFLOW_EN(bp) ((bp)->fw_cap & BNXT_FW_CAP_TRUFLOW_EN) > + #define BNXT_FW_CAP_RX_ALL_PKT_TS BIT_ULL(41) > + #define BNXT_FW_CAP_BACKING_STORE_V2 BIT_ULL(42) > + #define BNXT_FW_CAP_DBR_SUPPORTED BIT_ULL(43) > + #define BNXT_FW_CAP_GENERIC_STATS BIT_ULL(44) > + #define BNXT_FW_CAP_DBR_PACING_SUPPORTED BIT_ULL(45) > + #define BNXT_FW_CAP_PTP_PTM BIT_ULL(46) > + #define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(47) > + #define BNXT_FW_CAP_ENABLE_RDMA_SRIOV BIT_ULL(48) > + #define BNXT_FW_CAP_RSS_TCAM BIT_ULL(49) > + uint32_t lpi_tmr_lo; > + uint32_t lpi_tmr_hi; > + /* copied from flags and flags2 in hwrm_port_phy_qcaps_output */ > + uint16_t phy_flags; > +#define BNXT_PHY_FL_EEE_CAP HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EEE_SUPPORTED > +#define BNXT_PHY_FL_EXT_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EXTERNAL_LPBK_SUPPORTED > +#define BNXT_PHY_FL_AN_PHY_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_AUTONEG_LPBK_SUPPORTED > +#define BNXT_PHY_FL_SHARED_PORT_CFG HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_SHARED_PHY_CFG_SUPPORTED > +#define BNXT_PHY_FL_PORT_STATS_NO_RESET HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_CUMULATIVE_COUNTERS_ON_RESET > +#define BNXT_PHY_FL_NO_PHY_LPBK HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_LOCAL_LPBK_NOT_SUPPORTED > +#define BNXT_PHY_FL_FW_MANAGED_LKDN HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_FW_MANAGED_LINK_DOWN > +#define BNXT_PHY_FL_NO_FCS HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_NO_FCS > +#define BNXT_PHY_FL_NO_PAUSE (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PAUSE_UNSUPPORTED << 8) > +#define BNXT_PHY_FL_NO_PFC (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED << 8) > +#define BNXT_PHY_FL_BANK_SEL (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_BANK_ADDR_SUPPORTED << 8) > }; > > struct bnxt_filter_info { > @@ -843,6 +948,17 @@ struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, > int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *bp, uint16_t i2c_addr, > uint16_t page_number, uint8_t bank, bool bank_sel_en, uint16_t start_addr, > uint16_t data_length, uint8_t *buf); > +void bnxt_dcb_init(struct bnxt_softc *softc); > +void bnxt_dcb_free(struct bnxt_softc *softc); > +uint8_t bnxt_dcb_setdcbx(struct bnxt_softc *softc, uint8_t mode); > +uint8_t bnxt_dcb_getdcbx(struct bnxt_softc *softc); > +int bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets); > +int bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets); > uint8_t get_phy_type(struct bnxt_softc *softc); > +int bnxt_dcb_ieee_getpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc); > +int bnxt_dcb_ieee_setpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc); > +int bnxt_dcb_ieee_setapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app); > +int bnxt_dcb_ieee_delapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app); > +int bnxt_dcb_ieee_listapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs); > > #endif /* _BNXT_H */ > diff --git a/sys/dev/bnxt/bnxt_en/bnxt_dcb.c b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c > new file mode 100644 > index 000000000000..e1e0581d3c24 > --- /dev/null > +++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c > @@ -0,0 +1,861 @@ > +/*- > + * Broadcom NetXtreme-C/E network driver. > + * > + * Copyright (c) 2024 Broadcom, All Rights Reserved. > + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS > + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF > + * THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <sys/endian.h> > +#include <linux/errno.h> > +#include <linux/bitops.h> > + > +#include "bnxt.h" > +#include "bnxt_hwrm.h" > +#include "bnxt_dcb.h" > +#include "hsi_struct_def.h" > + > +static int > +bnxt_tx_queue_to_tc(struct bnxt_softc *softc, uint8_t queue_id) > +{ > + int i, j; > + > + for (i = 0; i < softc->max_tc; i++) { > + if (softc->tx_q_info[i].queue_id == queue_id) { > + for (j = 0; j < softc->max_tc; j++) { > + if (softc->tc_to_qidx[j] == i) > + return j; > + } > + } > + } > + return -EINVAL; > +} > + > +static int > +bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc *softc, > + struct bnxt_ieee_ets *ets, > + uint32_t path_dir) > +{ > + struct hwrm_queue_pri2cos_cfg_input req = {0}; > + struct bnxt_queue_info *q_info; > + uint8_t *pri2cos; > + int i; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_CFG); > + > + req.flags = htole32(path_dir | HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN); > + if (path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR || > + path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX) > + q_info = softc->tx_q_info; > + else > + q_info = softc->rx_q_info; > + pri2cos = &req.pri0_cos_queue_id; > + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { > + uint8_t qidx; > + > + req.enables |= htole32(HWRM_QUEUE_PRI2COS_CFG_INPUT_ENABLES_PRI0_COS_QUEUE_ID << i); > + > + qidx = softc->tc_to_qidx[ets->prio_tc[i]]; > + pri2cos[i] = q_info[qidx].queue_id; > + } > + return _hwrm_send_message(softc, &req, sizeof(req)); > +} > + > +static int > +bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) > +{ > + struct hwrm_queue_pri2cos_qcfg_output *resp = > + (void *)softc->hwrm_cmd_resp.idi_vaddr; > + struct hwrm_queue_pri2cos_qcfg_input req = {0}; > + int rc; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG); > + > + req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN); > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + if (!rc) { > + uint8_t *pri2cos = &resp->pri0_cos_queue_id; > + int i; > + > + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { > + uint8_t queue_id = pri2cos[i]; > + int tc; > + > + tc = bnxt_tx_queue_to_tc(softc, queue_id); > + if (tc >= 0) > + ets->prio_tc[i] = tc; > + } > + } > + return rc; > +} > + > +static int > +bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, > + uint8_t max_tc) > +{ > + struct hwrm_queue_cos2bw_cfg_input req = {0}; > + struct bnxt_cos2bw_cfg cos2bw; > + void *data; > + int i; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_CFG); > + > + for (i = 0; i < max_tc; i++) { > + uint8_t qidx = softc->tc_to_qidx[i]; > + > + req.enables |= > + htole32(HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID << qidx); > + > + memset(&cos2bw, 0, sizeof(cos2bw)); > + cos2bw.queue_id = softc->tx_q_info[qidx].queue_id; > + if (ets->tc_tsa[i] == BNXT_IEEE_8021QAZ_TSA_STRICT) { > + cos2bw.tsa = > + HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP; > + cos2bw.pri_lvl = i; > + } else { > + cos2bw.tsa = > + HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS; > + cos2bw.bw_weight = ets->tc_tx_bw[i]; > + /* older firmware requires min_bw to be set to the > + * same weight value in percent. > + */ > + if (BNXT_FW_MAJ(softc) < 218) { > + cos2bw.min_bw = > + htole32((ets->tc_tx_bw[i] * 100) | > + BW_VALUE_UNIT_PERCENT1_100); > + } > + } > + data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4); > + memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4); > + if (qidx == 0) { > + req.queue_id0 = cos2bw.queue_id; > + req.unused_0 = 0; > + } > + } > + return _hwrm_send_message(softc, &req, sizeof(req)); > +} > + > +static int > +bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) > +{ > + struct hwrm_queue_cos2bw_qcfg_output *resp = > + (void *)softc->hwrm_cmd_resp.idi_vaddr; > + struct hwrm_queue_cos2bw_qcfg_input req = {0}; > + struct bnxt_cos2bw_cfg cos2bw; > + uint8_t *data; > + int rc, i; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_QCFG); > + > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + if (rc) { > + return rc; > + } > + > + data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); > + for (i = 0; i < softc->max_tc; i++, data += sizeof(cos2bw.cfg)) { > + int tc; > + > + memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg)); > + if (i == 0) > + cos2bw.queue_id = resp->queue_id0; > + > + tc = bnxt_tx_queue_to_tc(softc, cos2bw.queue_id); > + if (tc < 0) > + continue; > + > + if (cos2bw.tsa == HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP) { > + ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_STRICT; > + } else { > + ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_ETS; > + ets->tc_tx_bw[tc] = cos2bw.bw_weight; > + } > + } > + return 0; > +} > + > +static int > +bnxt_queue_remap(struct bnxt_softc *softc, unsigned int lltc_mask) > +{ > + unsigned long qmap = 0; > + int max = softc->max_tc; > + int i, j, rc; > + > + /* Assign lossless TCs first */ > + for (i = 0, j = 0; i < max; ) { > + if (lltc_mask & (1 << i)) { > + if (BNXT_LLQ(softc->rx_q_info[j].queue_profile)) { > + softc->tc_to_qidx[i] = j; > + __set_bit(j, &qmap); > + i++; > + } > + j++; > + continue; > + } > + i++; > + } > + > + for (i = 0, j = 0; i < max; i++) { > + if (lltc_mask & (1 << i)) > + continue; > + j = find_next_zero_bit(&qmap, max, j); > + softc->tc_to_qidx[i] = j; > + __set_bit(j, &qmap); > + j++; > + } > + > + if (softc->ieee_ets) { > + rc = bnxt_hwrm_queue_cos2bw_cfg(softc, softc->ieee_ets, softc->max_tc); > + if (rc) { > + device_printf(softc->dev, "failed to config BW, rc = %d\n", rc); > + return rc; > + } > + rc = bnxt_hwrm_queue_pri2cos_cfg(softc, softc->ieee_ets, > + HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR); > + if (rc) { > + device_printf(softc->dev, "failed to config prio, rc = %d\n", rc); > + return rc; > + } > + } > + return 0; > +} > + > +static int > +bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) > +{ > + struct hwrm_queue_pfcenable_cfg_input req = {0}; > + struct bnxt_ieee_ets *my_ets = softc->ieee_ets; > + unsigned int tc_mask = 0, pri_mask = 0; > + uint8_t i, pri, lltc_count = 0; > + bool need_q_remap = false; > + > + if (!my_ets) > + return -EINVAL; > + > + for (i = 0; i < softc->max_tc; i++) { > + for (pri = 0; pri < BNXT_IEEE_8021QAZ_MAX_TCS; pri++) { > + if ((pfc->pfc_en & (1 << pri)) && > + (my_ets->prio_tc[pri] == i)) { > + pri_mask |= 1 << pri; > + tc_mask |= 1 << i; > + } > + } > + if (tc_mask & (1 << i)) > + lltc_count++; > + } > + > + if (lltc_count > softc->max_lltc) { > + device_printf(softc->dev, > + "Hardware doesn't support %d lossless queues " > + "to configure PFC (cap %d)\n", lltc_count, softc->max_lltc); > + return -EINVAL; > + } > + > + for (i = 0; i < softc->max_tc; i++) { > + if (tc_mask & (1 << i)) { > + uint8_t qidx = softc->tc_to_qidx[i]; > + > + if (!BNXT_LLQ(softc->rx_q_info[qidx].queue_profile)) { > + need_q_remap = true; > + break; > + } > + } > + } > + > + if (need_q_remap) > + bnxt_queue_remap(softc, tc_mask); > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_CFG); > + > + req.flags = htole32(pri_mask); > + return _hwrm_send_message(softc, &req, sizeof(req)); > +} > + > +static int > +bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) > +{ > + struct hwrm_queue_pfcenable_qcfg_output *resp = > + (void *)softc->hwrm_cmd_resp.idi_vaddr; > + struct hwrm_queue_pfcenable_qcfg_input req = {0}; > + uint8_t pri_mask; > + int rc; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_QCFG); > + > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + if (rc) { > + return rc; > + } > + > + pri_mask = le32toh(resp->flags); > + pfc->pfc_en = pri_mask; > + return 0; > +} > + > +static int > +bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs) > +{ > + struct hwrm_fw_get_structured_data_input get = {0}; > + struct hwrm_struct_data_dcbx_app *fw_app; > + struct hwrm_struct_hdr *data; > + struct iflib_dma_info dma_data; > + size_t data_len; > + int rc, n, i; > + > + if (softc->hwrm_spec_code < 0x10601) > + return 0; > + > + bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); > + > + n = BNXT_IEEE_8021QAZ_MAX_TCS; > + data_len = sizeof(*data) + sizeof(*fw_app) * n; > + rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, > + BUS_DMA_NOWAIT); > + if (rc) > + return ENOMEM; > + get.dest_data_addr = htole64(dma_data.idi_paddr); > + get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); > + get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); > + get.count = 0; > + rc = _hwrm_send_message(softc, &get, sizeof(get)); > + if (rc) > + goto set_app_exit; > + > + data = (void *)dma_data.idi_vaddr; > + fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); > + > + if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { > + rc = -ENODEV; > + goto set_app_exit; > + } > + > + n = data->count; > + for (i = 0; i < n; i++, fw_app++) { > + app[*num_inputs].priority = fw_app->priority; > + app[*num_inputs].protocol = htobe16(fw_app->protocol_id); > + app[*num_inputs].selector = fw_app->protocol_selector; > + (*num_inputs)++; > + } > + > +set_app_exit: > + iflib_dma_free(&dma_data); > + return rc; > +} > + > +static int > +bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, > + bool add) > +{ > + struct hwrm_fw_set_structured_data_input set = {0}; > + struct hwrm_fw_get_structured_data_input get = {0}; > + struct hwrm_struct_data_dcbx_app *fw_app; > + struct hwrm_struct_hdr *data; > + struct iflib_dma_info dma_data; > + size_t data_len; > + int rc, n, i; > + > + if (softc->hwrm_spec_code < 0x10601) > + return 0; > + > + bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); > + > + n = BNXT_IEEE_8021QAZ_MAX_TCS; > + data_len = sizeof(*data) + sizeof(*fw_app) * n; > + rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, > + BUS_DMA_NOWAIT); > + if (rc) > + return ENOMEM; > + get.dest_data_addr = htole64(dma_data.idi_paddr); > + get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); > + get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); > + get.count = 0; > + rc = _hwrm_send_message(softc, &get, sizeof(get)); > + if (rc) > + goto set_app_exit; > + > + data = (void *)dma_data.idi_vaddr; > + fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); > + > + if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { > + rc = -ENODEV; > + goto set_app_exit; > + } > + > + n = data->count; > + for (i = 0; i < n; i++, fw_app++) { > + if (fw_app->protocol_id == htobe16(app->protocol) && > + fw_app->protocol_selector == app->selector && > + fw_app->priority == app->priority) { > + if (add) > + goto set_app_exit; > + else > + break; > + } > + } > + if (add) { > + /* append */ > + n++; > + fw_app->protocol_id = htobe16(app->protocol); > + fw_app->protocol_selector = app->selector; > + fw_app->priority = app->priority; > + fw_app->valid = 1; > + } else { > + size_t len = 0; > + > + /* not found, nothing to delete */ > + if (n == i) > + goto set_app_exit; > + > + len = (n - 1 - i) * sizeof(*fw_app); > + if (len) > + memmove(fw_app, fw_app + 1, len); > + n--; > + memset(fw_app + n, 0, sizeof(*fw_app)); > + } > + data->count = n; > + data->len = htole16(sizeof(*fw_app) * n); > + data->subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); > + > + bnxt_hwrm_cmd_hdr_init(softc, &set, HWRM_FW_SET_STRUCTURED_DATA); > + > + set.src_data_addr = htole64(dma_data.idi_paddr); > + set.data_len = htole16(sizeof(*data) + sizeof(*fw_app) * n); > + set.hdr_cnt = 1; > + rc = _hwrm_send_message(softc, &set, sizeof(set)); > + > +set_app_exit: > + iflib_dma_free(&dma_data); > + return rc; > +} > + > +static int > +bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc *softc) > +{ > + struct hwrm_queue_dscp_qcaps_output *resp = > + (void *)softc->hwrm_cmd_resp.idi_vaddr; > + struct hwrm_queue_dscp_qcaps_input req = {0}; > + int rc; > + > + softc->max_dscp_value = 0; > + if (softc->hwrm_spec_code < 0x10800 || BNXT_VF(softc)) > + return 0; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP_QCAPS); > + > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + if (!rc) { > + softc->max_dscp_value = (1 << resp->num_dscp_bits) - 1; > + if (softc->max_dscp_value < 0x3f) > + softc->max_dscp_value = 0; > + } > + return rc; > +} > + > +static int > +bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs) > +{ > + struct hwrm_queue_dscp2pri_qcfg_input req = {0}; > + struct hwrm_queue_dscp2pri_qcfg_output *resp = > + (void *)softc->hwrm_cmd_resp.idi_vaddr; > + struct bnxt_dscp2pri_entry *dscp2pri; > + struct iflib_dma_info dma_data; > + int rc, entry_cnt; > + int i; > + > + if (softc->hwrm_spec_code < 0x10800) > + return 0; > + > + rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri) * 128, &dma_data, > + BUS_DMA_NOWAIT); > + if (rc) > + return ENOMEM; > + > + dscp2pri = (void *)dma_data.idi_vaddr; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_QCFG); > + > + req.dest_data_addr = htole64(dma_data.idi_paddr); > + req.dest_data_buffer_size = htole16(sizeof(*dscp2pri) * 64); > + req.port_id = htole16(softc->pf.port_id); > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + > + if (rc) > + goto end; > + > + entry_cnt = le16toh(resp->entry_cnt); > + for (i = 0; i < entry_cnt; i++) { > + app[*num_inputs].priority = dscp2pri[i].pri; > + app[*num_inputs].protocol = dscp2pri[i].dscp; > + app[*num_inputs].selector = BNXT_IEEE_8021QAZ_APP_SEL_DSCP; > + (*num_inputs)++; > + } > + > +end: > + iflib_dma_free(&dma_data); > + return rc; > +} > + > +static int > +bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, > + bool add) > +{ > + struct hwrm_queue_dscp2pri_cfg_input req = {0}; > + struct bnxt_dscp2pri_entry *dscp2pri; > + struct iflib_dma_info dma_data; > + int rc; > + > + if (softc->hwrm_spec_code < 0x10800) > + return 0; > + > + rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri), &dma_data, > + BUS_DMA_NOWAIT); > + if (rc) > + return ENOMEM; > + > + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_CFG); > + > + req.src_data_addr = htole64(dma_data.idi_paddr); > + dscp2pri = (void *)dma_data.idi_vaddr; > + dscp2pri->dscp = app->protocol; > + if (add) > + dscp2pri->mask = 0x3f; > + else > + dscp2pri->mask = 0; > + dscp2pri->pri = app->priority; > + req.entry_cnt = htole16(1); > + req.port_id = htole16(softc->pf.port_id); > + rc = _hwrm_send_message(softc, &req, sizeof(req)); > + > + iflib_dma_free(&dma_data); > + return rc; > +} > + > +static int > +bnxt_ets_validate(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, uint8_t *tc) > +{ > + int total_ets_bw = 0; > + bool zero = false; > + uint8_t max_tc = 0; > + int i; > + > + for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { > + if (ets->prio_tc[i] > softc->max_tc) { > + device_printf(softc->dev, "priority to TC mapping exceeds TC count %d\n", > + ets->prio_tc[i]); > + return -EINVAL; > + } > + if (ets->prio_tc[i] > max_tc) > + max_tc = ets->prio_tc[i]; > + > + if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > softc->max_tc) > + return -EINVAL; > + > + switch (ets->tc_tsa[i]) { > + case BNXT_IEEE_8021QAZ_TSA_STRICT: > + break; > + case BNXT_IEEE_8021QAZ_TSA_ETS: > + total_ets_bw += ets->tc_tx_bw[i]; > + zero = zero || !ets->tc_tx_bw[i]; > + break; > + default: > + return -ENOTSUPP; > + } > + } > + if (total_ets_bw > 100) { > + device_printf(softc->dev, "rejecting ETS config exceeding available bandwidth\n"); > + return -EINVAL; > + } > + if (zero && total_ets_bw == 100) { > + device_printf(softc->dev, "rejecting ETS config starving a TC\n"); > + return -EINVAL; > + } > + > + if (max_tc >= softc->max_tc) > + *tc = softc->max_tc; > + else > + *tc = max_tc + 1; > + return 0; > +} > + > +int > +bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) > +{ > + struct bnxt_ieee_ets *my_ets = softc->ieee_ets; > + int rc; > + > + if (!my_ets) > + return 0; > + > + rc = bnxt_hwrm_queue_cos2bw_qcfg(softc, my_ets); > + if (rc) > + goto error; > + rc = bnxt_hwrm_queue_pri2cos_qcfg(softc, my_ets); > + if (rc) > + goto error; > + > + if (ets) { > + ets->cbs = my_ets->cbs; > + ets->ets_cap = softc->max_tc; > + memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); > + memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); > + memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); > + memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); > + } > + return 0; > +error: > + return rc; > +} > + > +int > +bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) > +{ > + uint8_t max_tc = 0; > + int rc; > *** 1821 LINES SKIPPED ***