1*35b53f8cSChandrakanth patil /*- 2*35b53f8cSChandrakanth patil * Broadcom NetXtreme-C/E network driver. 3*35b53f8cSChandrakanth patil * 4*35b53f8cSChandrakanth patil * Copyright (c) 2024 Broadcom, All Rights Reserved. 5*35b53f8cSChandrakanth patil * The term Broadcom refers to Broadcom Limited and/or its subsidiaries 6*35b53f8cSChandrakanth patil * 7*35b53f8cSChandrakanth patil * Redistribution and use in source and binary forms, with or without 8*35b53f8cSChandrakanth patil * modification, are permitted provided that the following conditions 9*35b53f8cSChandrakanth patil * are met: 10*35b53f8cSChandrakanth patil * 1. Redistributions of source code must retain the above copyright 11*35b53f8cSChandrakanth patil * notice, this list of conditions and the following disclaimer. 12*35b53f8cSChandrakanth patil * 2. Redistributions in binary form must reproduce the above copyright 13*35b53f8cSChandrakanth patil * notice, this list of conditions and the following disclaimer in the 14*35b53f8cSChandrakanth patil * documentation and/or other materials provided with the distribution. 15*35b53f8cSChandrakanth patil * 16*35b53f8cSChandrakanth patil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 17*35b53f8cSChandrakanth patil * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*35b53f8cSChandrakanth patil * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*35b53f8cSChandrakanth patil * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20*35b53f8cSChandrakanth patil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*35b53f8cSChandrakanth patil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*35b53f8cSChandrakanth patil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*35b53f8cSChandrakanth patil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*35b53f8cSChandrakanth patil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*35b53f8cSChandrakanth patil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26*35b53f8cSChandrakanth patil * THE POSSIBILITY OF SUCH DAMAGE. 27*35b53f8cSChandrakanth patil */ 28*35b53f8cSChandrakanth patil 29*35b53f8cSChandrakanth patil #include <sys/endian.h> 30*35b53f8cSChandrakanth patil #include <linux/errno.h> 31*35b53f8cSChandrakanth patil #include <linux/bitops.h> 32*35b53f8cSChandrakanth patil 33*35b53f8cSChandrakanth patil #include "bnxt.h" 34*35b53f8cSChandrakanth patil #include "bnxt_hwrm.h" 35*35b53f8cSChandrakanth patil #include "bnxt_dcb.h" 36*35b53f8cSChandrakanth patil #include "hsi_struct_def.h" 37*35b53f8cSChandrakanth patil 38*35b53f8cSChandrakanth patil static int 39*35b53f8cSChandrakanth patil bnxt_tx_queue_to_tc(struct bnxt_softc *softc, uint8_t queue_id) 40*35b53f8cSChandrakanth patil { 41*35b53f8cSChandrakanth patil int i, j; 42*35b53f8cSChandrakanth patil 43*35b53f8cSChandrakanth patil for (i = 0; i < softc->max_tc; i++) { 44*35b53f8cSChandrakanth patil if (softc->tx_q_info[i].queue_id == queue_id) { 45*35b53f8cSChandrakanth patil for (j = 0; j < softc->max_tc; j++) { 46*35b53f8cSChandrakanth patil if (softc->tc_to_qidx[j] == i) 47*35b53f8cSChandrakanth patil return j; 48*35b53f8cSChandrakanth patil } 49*35b53f8cSChandrakanth patil } 50*35b53f8cSChandrakanth patil } 51*35b53f8cSChandrakanth patil return -EINVAL; 52*35b53f8cSChandrakanth patil } 53*35b53f8cSChandrakanth patil 54*35b53f8cSChandrakanth patil static int 55*35b53f8cSChandrakanth patil bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc *softc, 56*35b53f8cSChandrakanth patil struct bnxt_ieee_ets *ets, 57*35b53f8cSChandrakanth patil uint32_t path_dir) 58*35b53f8cSChandrakanth patil { 59*35b53f8cSChandrakanth patil struct hwrm_queue_pri2cos_cfg_input req = {0}; 60*35b53f8cSChandrakanth patil struct bnxt_queue_info *q_info; 61*35b53f8cSChandrakanth patil uint8_t *pri2cos; 62*35b53f8cSChandrakanth patil int i; 63*35b53f8cSChandrakanth patil 64*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_CFG); 65*35b53f8cSChandrakanth patil 66*35b53f8cSChandrakanth patil req.flags = htole32(path_dir | HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN); 67*35b53f8cSChandrakanth patil if (path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR || 68*35b53f8cSChandrakanth patil path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX) 69*35b53f8cSChandrakanth patil q_info = softc->tx_q_info; 70*35b53f8cSChandrakanth patil else 71*35b53f8cSChandrakanth patil q_info = softc->rx_q_info; 72*35b53f8cSChandrakanth patil pri2cos = &req.pri0_cos_queue_id; 73*35b53f8cSChandrakanth patil for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { 74*35b53f8cSChandrakanth patil uint8_t qidx; 75*35b53f8cSChandrakanth patil 76*35b53f8cSChandrakanth patil req.enables |= htole32(HWRM_QUEUE_PRI2COS_CFG_INPUT_ENABLES_PRI0_COS_QUEUE_ID << i); 77*35b53f8cSChandrakanth patil 78*35b53f8cSChandrakanth patil qidx = softc->tc_to_qidx[ets->prio_tc[i]]; 79*35b53f8cSChandrakanth patil pri2cos[i] = q_info[qidx].queue_id; 80*35b53f8cSChandrakanth patil } 81*35b53f8cSChandrakanth patil return _hwrm_send_message(softc, &req, sizeof(req)); 82*35b53f8cSChandrakanth patil } 83*35b53f8cSChandrakanth patil 84*35b53f8cSChandrakanth patil static int 85*35b53f8cSChandrakanth patil bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) 86*35b53f8cSChandrakanth patil { 87*35b53f8cSChandrakanth patil struct hwrm_queue_pri2cos_qcfg_output *resp = 88*35b53f8cSChandrakanth patil (void *)softc->hwrm_cmd_resp.idi_vaddr; 89*35b53f8cSChandrakanth patil struct hwrm_queue_pri2cos_qcfg_input req = {0}; 90*35b53f8cSChandrakanth patil int rc; 91*35b53f8cSChandrakanth patil 92*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG); 93*35b53f8cSChandrakanth patil 94*35b53f8cSChandrakanth patil req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN); 95*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 96*35b53f8cSChandrakanth patil if (!rc) { 97*35b53f8cSChandrakanth patil uint8_t *pri2cos = &resp->pri0_cos_queue_id; 98*35b53f8cSChandrakanth patil int i; 99*35b53f8cSChandrakanth patil 100*35b53f8cSChandrakanth patil for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { 101*35b53f8cSChandrakanth patil uint8_t queue_id = pri2cos[i]; 102*35b53f8cSChandrakanth patil int tc; 103*35b53f8cSChandrakanth patil 104*35b53f8cSChandrakanth patil tc = bnxt_tx_queue_to_tc(softc, queue_id); 105*35b53f8cSChandrakanth patil if (tc >= 0) 106*35b53f8cSChandrakanth patil ets->prio_tc[i] = tc; 107*35b53f8cSChandrakanth patil } 108*35b53f8cSChandrakanth patil } 109*35b53f8cSChandrakanth patil return rc; 110*35b53f8cSChandrakanth patil } 111*35b53f8cSChandrakanth patil 112*35b53f8cSChandrakanth patil static int 113*35b53f8cSChandrakanth patil bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, 114*35b53f8cSChandrakanth patil uint8_t max_tc) 115*35b53f8cSChandrakanth patil { 116*35b53f8cSChandrakanth patil struct hwrm_queue_cos2bw_cfg_input req = {0}; 117*35b53f8cSChandrakanth patil struct bnxt_cos2bw_cfg cos2bw; 118*35b53f8cSChandrakanth patil void *data; 119*35b53f8cSChandrakanth patil int i; 120*35b53f8cSChandrakanth patil 121*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_CFG); 122*35b53f8cSChandrakanth patil 123*35b53f8cSChandrakanth patil for (i = 0; i < max_tc; i++) { 124*35b53f8cSChandrakanth patil uint8_t qidx = softc->tc_to_qidx[i]; 125*35b53f8cSChandrakanth patil 126*35b53f8cSChandrakanth patil req.enables |= 127*35b53f8cSChandrakanth patil htole32(HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID << qidx); 128*35b53f8cSChandrakanth patil 129*35b53f8cSChandrakanth patil memset(&cos2bw, 0, sizeof(cos2bw)); 130*35b53f8cSChandrakanth patil cos2bw.queue_id = softc->tx_q_info[qidx].queue_id; 131*35b53f8cSChandrakanth patil if (ets->tc_tsa[i] == BNXT_IEEE_8021QAZ_TSA_STRICT) { 132*35b53f8cSChandrakanth patil cos2bw.tsa = 133*35b53f8cSChandrakanth patil HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP; 134*35b53f8cSChandrakanth patil cos2bw.pri_lvl = i; 135*35b53f8cSChandrakanth patil } else { 136*35b53f8cSChandrakanth patil cos2bw.tsa = 137*35b53f8cSChandrakanth patil HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS; 138*35b53f8cSChandrakanth patil cos2bw.bw_weight = ets->tc_tx_bw[i]; 139*35b53f8cSChandrakanth patil /* older firmware requires min_bw to be set to the 140*35b53f8cSChandrakanth patil * same weight value in percent. 141*35b53f8cSChandrakanth patil */ 142*35b53f8cSChandrakanth patil if (BNXT_FW_MAJ(softc) < 218) { 143*35b53f8cSChandrakanth patil cos2bw.min_bw = 144*35b53f8cSChandrakanth patil htole32((ets->tc_tx_bw[i] * 100) | 145*35b53f8cSChandrakanth patil BW_VALUE_UNIT_PERCENT1_100); 146*35b53f8cSChandrakanth patil } 147*35b53f8cSChandrakanth patil } 148*35b53f8cSChandrakanth patil data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4); 149*35b53f8cSChandrakanth patil memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4); 150*35b53f8cSChandrakanth patil if (qidx == 0) { 151*35b53f8cSChandrakanth patil req.queue_id0 = cos2bw.queue_id; 152*35b53f8cSChandrakanth patil req.unused_0 = 0; 153*35b53f8cSChandrakanth patil } 154*35b53f8cSChandrakanth patil } 155*35b53f8cSChandrakanth patil return _hwrm_send_message(softc, &req, sizeof(req)); 156*35b53f8cSChandrakanth patil } 157*35b53f8cSChandrakanth patil 158*35b53f8cSChandrakanth patil static int 159*35b53f8cSChandrakanth patil bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) 160*35b53f8cSChandrakanth patil { 161*35b53f8cSChandrakanth patil struct hwrm_queue_cos2bw_qcfg_output *resp = 162*35b53f8cSChandrakanth patil (void *)softc->hwrm_cmd_resp.idi_vaddr; 163*35b53f8cSChandrakanth patil struct hwrm_queue_cos2bw_qcfg_input req = {0}; 164*35b53f8cSChandrakanth patil struct bnxt_cos2bw_cfg cos2bw; 165*35b53f8cSChandrakanth patil uint8_t *data; 166*35b53f8cSChandrakanth patil int rc, i; 167*35b53f8cSChandrakanth patil 168*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_QCFG); 169*35b53f8cSChandrakanth patil 170*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 171*35b53f8cSChandrakanth patil if (rc) { 172*35b53f8cSChandrakanth patil return rc; 173*35b53f8cSChandrakanth patil } 174*35b53f8cSChandrakanth patil 175*35b53f8cSChandrakanth patil data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); 176*35b53f8cSChandrakanth patil for (i = 0; i < softc->max_tc; i++, data += sizeof(cos2bw.cfg)) { 177*35b53f8cSChandrakanth patil int tc; 178*35b53f8cSChandrakanth patil 179*35b53f8cSChandrakanth patil memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg)); 180*35b53f8cSChandrakanth patil if (i == 0) 181*35b53f8cSChandrakanth patil cos2bw.queue_id = resp->queue_id0; 182*35b53f8cSChandrakanth patil 183*35b53f8cSChandrakanth patil tc = bnxt_tx_queue_to_tc(softc, cos2bw.queue_id); 184*35b53f8cSChandrakanth patil if (tc < 0) 185*35b53f8cSChandrakanth patil continue; 186*35b53f8cSChandrakanth patil 187*35b53f8cSChandrakanth patil if (cos2bw.tsa == HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP) { 188*35b53f8cSChandrakanth patil ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_STRICT; 189*35b53f8cSChandrakanth patil } else { 190*35b53f8cSChandrakanth patil ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_ETS; 191*35b53f8cSChandrakanth patil ets->tc_tx_bw[tc] = cos2bw.bw_weight; 192*35b53f8cSChandrakanth patil } 193*35b53f8cSChandrakanth patil } 194*35b53f8cSChandrakanth patil return 0; 195*35b53f8cSChandrakanth patil } 196*35b53f8cSChandrakanth patil 197*35b53f8cSChandrakanth patil static int 198*35b53f8cSChandrakanth patil bnxt_queue_remap(struct bnxt_softc *softc, unsigned int lltc_mask) 199*35b53f8cSChandrakanth patil { 200*35b53f8cSChandrakanth patil unsigned long qmap = 0; 201*35b53f8cSChandrakanth patil int max = softc->max_tc; 202*35b53f8cSChandrakanth patil int i, j, rc; 203*35b53f8cSChandrakanth patil 204*35b53f8cSChandrakanth patil /* Assign lossless TCs first */ 205*35b53f8cSChandrakanth patil for (i = 0, j = 0; i < max; ) { 206*35b53f8cSChandrakanth patil if (lltc_mask & (1 << i)) { 207*35b53f8cSChandrakanth patil if (BNXT_LLQ(softc->rx_q_info[j].queue_profile)) { 208*35b53f8cSChandrakanth patil softc->tc_to_qidx[i] = j; 209*35b53f8cSChandrakanth patil __set_bit(j, &qmap); 210*35b53f8cSChandrakanth patil i++; 211*35b53f8cSChandrakanth patil } 212*35b53f8cSChandrakanth patil j++; 213*35b53f8cSChandrakanth patil continue; 214*35b53f8cSChandrakanth patil } 215*35b53f8cSChandrakanth patil i++; 216*35b53f8cSChandrakanth patil } 217*35b53f8cSChandrakanth patil 218*35b53f8cSChandrakanth patil for (i = 0, j = 0; i < max; i++) { 219*35b53f8cSChandrakanth patil if (lltc_mask & (1 << i)) 220*35b53f8cSChandrakanth patil continue; 221*35b53f8cSChandrakanth patil j = find_next_zero_bit(&qmap, max, j); 222*35b53f8cSChandrakanth patil softc->tc_to_qidx[i] = j; 223*35b53f8cSChandrakanth patil __set_bit(j, &qmap); 224*35b53f8cSChandrakanth patil j++; 225*35b53f8cSChandrakanth patil } 226*35b53f8cSChandrakanth patil 227*35b53f8cSChandrakanth patil if (softc->ieee_ets) { 228*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_cos2bw_cfg(softc, softc->ieee_ets, softc->max_tc); 229*35b53f8cSChandrakanth patil if (rc) { 230*35b53f8cSChandrakanth patil device_printf(softc->dev, "failed to config BW, rc = %d\n", rc); 231*35b53f8cSChandrakanth patil return rc; 232*35b53f8cSChandrakanth patil } 233*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pri2cos_cfg(softc, softc->ieee_ets, 234*35b53f8cSChandrakanth patil HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR); 235*35b53f8cSChandrakanth patil if (rc) { 236*35b53f8cSChandrakanth patil device_printf(softc->dev, "failed to config prio, rc = %d\n", rc); 237*35b53f8cSChandrakanth patil return rc; 238*35b53f8cSChandrakanth patil } 239*35b53f8cSChandrakanth patil } 240*35b53f8cSChandrakanth patil return 0; 241*35b53f8cSChandrakanth patil } 242*35b53f8cSChandrakanth patil 243*35b53f8cSChandrakanth patil static int 244*35b53f8cSChandrakanth patil bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) 245*35b53f8cSChandrakanth patil { 246*35b53f8cSChandrakanth patil struct hwrm_queue_pfcenable_cfg_input req = {0}; 247*35b53f8cSChandrakanth patil struct bnxt_ieee_ets *my_ets = softc->ieee_ets; 248*35b53f8cSChandrakanth patil unsigned int tc_mask = 0, pri_mask = 0; 249*35b53f8cSChandrakanth patil uint8_t i, pri, lltc_count = 0; 250*35b53f8cSChandrakanth patil bool need_q_remap = false; 251*35b53f8cSChandrakanth patil 252*35b53f8cSChandrakanth patil if (!my_ets) 253*35b53f8cSChandrakanth patil return -EINVAL; 254*35b53f8cSChandrakanth patil 255*35b53f8cSChandrakanth patil for (i = 0; i < softc->max_tc; i++) { 256*35b53f8cSChandrakanth patil for (pri = 0; pri < BNXT_IEEE_8021QAZ_MAX_TCS; pri++) { 257*35b53f8cSChandrakanth patil if ((pfc->pfc_en & (1 << pri)) && 258*35b53f8cSChandrakanth patil (my_ets->prio_tc[pri] == i)) { 259*35b53f8cSChandrakanth patil pri_mask |= 1 << pri; 260*35b53f8cSChandrakanth patil tc_mask |= 1 << i; 261*35b53f8cSChandrakanth patil } 262*35b53f8cSChandrakanth patil } 263*35b53f8cSChandrakanth patil if (tc_mask & (1 << i)) 264*35b53f8cSChandrakanth patil lltc_count++; 265*35b53f8cSChandrakanth patil } 266*35b53f8cSChandrakanth patil 267*35b53f8cSChandrakanth patil if (lltc_count > softc->max_lltc) { 268*35b53f8cSChandrakanth patil device_printf(softc->dev, 269*35b53f8cSChandrakanth patil "Hardware doesn't support %d lossless queues " 270*35b53f8cSChandrakanth patil "to configure PFC (cap %d)\n", lltc_count, softc->max_lltc); 271*35b53f8cSChandrakanth patil return -EINVAL; 272*35b53f8cSChandrakanth patil } 273*35b53f8cSChandrakanth patil 274*35b53f8cSChandrakanth patil for (i = 0; i < softc->max_tc; i++) { 275*35b53f8cSChandrakanth patil if (tc_mask & (1 << i)) { 276*35b53f8cSChandrakanth patil uint8_t qidx = softc->tc_to_qidx[i]; 277*35b53f8cSChandrakanth patil 278*35b53f8cSChandrakanth patil if (!BNXT_LLQ(softc->rx_q_info[qidx].queue_profile)) { 279*35b53f8cSChandrakanth patil need_q_remap = true; 280*35b53f8cSChandrakanth patil break; 281*35b53f8cSChandrakanth patil } 282*35b53f8cSChandrakanth patil } 283*35b53f8cSChandrakanth patil } 284*35b53f8cSChandrakanth patil 285*35b53f8cSChandrakanth patil if (need_q_remap) 286*35b53f8cSChandrakanth patil bnxt_queue_remap(softc, tc_mask); 287*35b53f8cSChandrakanth patil 288*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_CFG); 289*35b53f8cSChandrakanth patil 290*35b53f8cSChandrakanth patil req.flags = htole32(pri_mask); 291*35b53f8cSChandrakanth patil return _hwrm_send_message(softc, &req, sizeof(req)); 292*35b53f8cSChandrakanth patil } 293*35b53f8cSChandrakanth patil 294*35b53f8cSChandrakanth patil static int 295*35b53f8cSChandrakanth patil bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) 296*35b53f8cSChandrakanth patil { 297*35b53f8cSChandrakanth patil struct hwrm_queue_pfcenable_qcfg_output *resp = 298*35b53f8cSChandrakanth patil (void *)softc->hwrm_cmd_resp.idi_vaddr; 299*35b53f8cSChandrakanth patil struct hwrm_queue_pfcenable_qcfg_input req = {0}; 300*35b53f8cSChandrakanth patil uint8_t pri_mask; 301*35b53f8cSChandrakanth patil int rc; 302*35b53f8cSChandrakanth patil 303*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_QCFG); 304*35b53f8cSChandrakanth patil 305*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 306*35b53f8cSChandrakanth patil if (rc) { 307*35b53f8cSChandrakanth patil return rc; 308*35b53f8cSChandrakanth patil } 309*35b53f8cSChandrakanth patil 310*35b53f8cSChandrakanth patil pri_mask = le32toh(resp->flags); 311*35b53f8cSChandrakanth patil pfc->pfc_en = pri_mask; 312*35b53f8cSChandrakanth patil return 0; 313*35b53f8cSChandrakanth patil } 314*35b53f8cSChandrakanth patil 315*35b53f8cSChandrakanth patil static int 316*35b53f8cSChandrakanth patil bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs) 317*35b53f8cSChandrakanth patil { 318*35b53f8cSChandrakanth patil struct hwrm_fw_get_structured_data_input get = {0}; 319*35b53f8cSChandrakanth patil struct hwrm_struct_data_dcbx_app *fw_app; 320*35b53f8cSChandrakanth patil struct hwrm_struct_hdr *data; 321*35b53f8cSChandrakanth patil struct iflib_dma_info dma_data; 322*35b53f8cSChandrakanth patil size_t data_len; 323*35b53f8cSChandrakanth patil int rc, n, i; 324*35b53f8cSChandrakanth patil 325*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10601) 326*35b53f8cSChandrakanth patil return 0; 327*35b53f8cSChandrakanth patil 328*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); 329*35b53f8cSChandrakanth patil 330*35b53f8cSChandrakanth patil n = BNXT_IEEE_8021QAZ_MAX_TCS; 331*35b53f8cSChandrakanth patil data_len = sizeof(*data) + sizeof(*fw_app) * n; 332*35b53f8cSChandrakanth patil rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, 333*35b53f8cSChandrakanth patil BUS_DMA_NOWAIT); 334*35b53f8cSChandrakanth patil if (rc) 335*35b53f8cSChandrakanth patil return ENOMEM; 336*35b53f8cSChandrakanth patil get.dest_data_addr = htole64(dma_data.idi_paddr); 337*35b53f8cSChandrakanth patil get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); 338*35b53f8cSChandrakanth patil get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); 339*35b53f8cSChandrakanth patil get.count = 0; 340*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &get, sizeof(get)); 341*35b53f8cSChandrakanth patil if (rc) 342*35b53f8cSChandrakanth patil goto set_app_exit; 343*35b53f8cSChandrakanth patil 344*35b53f8cSChandrakanth patil data = (void *)dma_data.idi_vaddr; 345*35b53f8cSChandrakanth patil fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); 346*35b53f8cSChandrakanth patil 347*35b53f8cSChandrakanth patil if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { 348*35b53f8cSChandrakanth patil rc = -ENODEV; 349*35b53f8cSChandrakanth patil goto set_app_exit; 350*35b53f8cSChandrakanth patil } 351*35b53f8cSChandrakanth patil 352*35b53f8cSChandrakanth patil n = data->count; 353*35b53f8cSChandrakanth patil for (i = 0; i < n; i++, fw_app++) { 354*35b53f8cSChandrakanth patil app[*num_inputs].priority = fw_app->priority; 355*35b53f8cSChandrakanth patil app[*num_inputs].protocol = htobe16(fw_app->protocol_id); 356*35b53f8cSChandrakanth patil app[*num_inputs].selector = fw_app->protocol_selector; 357*35b53f8cSChandrakanth patil (*num_inputs)++; 358*35b53f8cSChandrakanth patil } 359*35b53f8cSChandrakanth patil 360*35b53f8cSChandrakanth patil set_app_exit: 361*35b53f8cSChandrakanth patil iflib_dma_free(&dma_data); 362*35b53f8cSChandrakanth patil return rc; 363*35b53f8cSChandrakanth patil } 364*35b53f8cSChandrakanth patil 365*35b53f8cSChandrakanth patil static int 366*35b53f8cSChandrakanth patil bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app, 367*35b53f8cSChandrakanth patil bool add) 368*35b53f8cSChandrakanth patil { 369*35b53f8cSChandrakanth patil struct hwrm_fw_set_structured_data_input set = {0}; 370*35b53f8cSChandrakanth patil struct hwrm_fw_get_structured_data_input get = {0}; 371*35b53f8cSChandrakanth patil struct hwrm_struct_data_dcbx_app *fw_app; 372*35b53f8cSChandrakanth patil struct hwrm_struct_hdr *data; 373*35b53f8cSChandrakanth patil struct iflib_dma_info dma_data; 374*35b53f8cSChandrakanth patil size_t data_len; 375*35b53f8cSChandrakanth patil int rc, n, i; 376*35b53f8cSChandrakanth patil 377*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10601) 378*35b53f8cSChandrakanth patil return 0; 379*35b53f8cSChandrakanth patil 380*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA); 381*35b53f8cSChandrakanth patil 382*35b53f8cSChandrakanth patil n = BNXT_IEEE_8021QAZ_MAX_TCS; 383*35b53f8cSChandrakanth patil data_len = sizeof(*data) + sizeof(*fw_app) * n; 384*35b53f8cSChandrakanth patil rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, 385*35b53f8cSChandrakanth patil BUS_DMA_NOWAIT); 386*35b53f8cSChandrakanth patil if (rc) 387*35b53f8cSChandrakanth patil return ENOMEM; 388*35b53f8cSChandrakanth patil get.dest_data_addr = htole64(dma_data.idi_paddr); 389*35b53f8cSChandrakanth patil get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP); 390*35b53f8cSChandrakanth patil get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); 391*35b53f8cSChandrakanth patil get.count = 0; 392*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &get, sizeof(get)); 393*35b53f8cSChandrakanth patil if (rc) 394*35b53f8cSChandrakanth patil goto set_app_exit; 395*35b53f8cSChandrakanth patil 396*35b53f8cSChandrakanth patil data = (void *)dma_data.idi_vaddr; 397*35b53f8cSChandrakanth patil fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); 398*35b53f8cSChandrakanth patil 399*35b53f8cSChandrakanth patil if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) { 400*35b53f8cSChandrakanth patil rc = -ENODEV; 401*35b53f8cSChandrakanth patil goto set_app_exit; 402*35b53f8cSChandrakanth patil } 403*35b53f8cSChandrakanth patil 404*35b53f8cSChandrakanth patil n = data->count; 405*35b53f8cSChandrakanth patil for (i = 0; i < n; i++, fw_app++) { 406*35b53f8cSChandrakanth patil if (fw_app->protocol_id == htobe16(app->protocol) && 407*35b53f8cSChandrakanth patil fw_app->protocol_selector == app->selector && 408*35b53f8cSChandrakanth patil fw_app->priority == app->priority) { 409*35b53f8cSChandrakanth patil if (add) 410*35b53f8cSChandrakanth patil goto set_app_exit; 411*35b53f8cSChandrakanth patil else 412*35b53f8cSChandrakanth patil break; 413*35b53f8cSChandrakanth patil } 414*35b53f8cSChandrakanth patil } 415*35b53f8cSChandrakanth patil if (add) { 416*35b53f8cSChandrakanth patil /* append */ 417*35b53f8cSChandrakanth patil n++; 418*35b53f8cSChandrakanth patil fw_app->protocol_id = htobe16(app->protocol); 419*35b53f8cSChandrakanth patil fw_app->protocol_selector = app->selector; 420*35b53f8cSChandrakanth patil fw_app->priority = app->priority; 421*35b53f8cSChandrakanth patil fw_app->valid = 1; 422*35b53f8cSChandrakanth patil } else { 423*35b53f8cSChandrakanth patil size_t len = 0; 424*35b53f8cSChandrakanth patil 425*35b53f8cSChandrakanth patil /* not found, nothing to delete */ 426*35b53f8cSChandrakanth patil if (n == i) 427*35b53f8cSChandrakanth patil goto set_app_exit; 428*35b53f8cSChandrakanth patil 429*35b53f8cSChandrakanth patil len = (n - 1 - i) * sizeof(*fw_app); 430*35b53f8cSChandrakanth patil if (len) 431*35b53f8cSChandrakanth patil memmove(fw_app, fw_app + 1, len); 432*35b53f8cSChandrakanth patil n--; 433*35b53f8cSChandrakanth patil memset(fw_app + n, 0, sizeof(*fw_app)); 434*35b53f8cSChandrakanth patil } 435*35b53f8cSChandrakanth patil data->count = n; 436*35b53f8cSChandrakanth patil data->len = htole16(sizeof(*fw_app) * n); 437*35b53f8cSChandrakanth patil data->subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); 438*35b53f8cSChandrakanth patil 439*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &set, HWRM_FW_SET_STRUCTURED_DATA); 440*35b53f8cSChandrakanth patil 441*35b53f8cSChandrakanth patil set.src_data_addr = htole64(dma_data.idi_paddr); 442*35b53f8cSChandrakanth patil set.data_len = htole16(sizeof(*data) + sizeof(*fw_app) * n); 443*35b53f8cSChandrakanth patil set.hdr_cnt = 1; 444*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &set, sizeof(set)); 445*35b53f8cSChandrakanth patil 446*35b53f8cSChandrakanth patil set_app_exit: 447*35b53f8cSChandrakanth patil iflib_dma_free(&dma_data); 448*35b53f8cSChandrakanth patil return rc; 449*35b53f8cSChandrakanth patil } 450*35b53f8cSChandrakanth patil 451*35b53f8cSChandrakanth patil static int 452*35b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc *softc) 453*35b53f8cSChandrakanth patil { 454*35b53f8cSChandrakanth patil struct hwrm_queue_dscp_qcaps_output *resp = 455*35b53f8cSChandrakanth patil (void *)softc->hwrm_cmd_resp.idi_vaddr; 456*35b53f8cSChandrakanth patil struct hwrm_queue_dscp_qcaps_input req = {0}; 457*35b53f8cSChandrakanth patil int rc; 458*35b53f8cSChandrakanth patil 459*35b53f8cSChandrakanth patil softc->max_dscp_value = 0; 460*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10800 || BNXT_VF(softc)) 461*35b53f8cSChandrakanth patil return 0; 462*35b53f8cSChandrakanth patil 463*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP_QCAPS); 464*35b53f8cSChandrakanth patil 465*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 466*35b53f8cSChandrakanth patil if (!rc) { 467*35b53f8cSChandrakanth patil softc->max_dscp_value = (1 << resp->num_dscp_bits) - 1; 468*35b53f8cSChandrakanth patil if (softc->max_dscp_value < 0x3f) 469*35b53f8cSChandrakanth patil softc->max_dscp_value = 0; 470*35b53f8cSChandrakanth patil } 471*35b53f8cSChandrakanth patil return rc; 472*35b53f8cSChandrakanth patil } 473*35b53f8cSChandrakanth patil 474*35b53f8cSChandrakanth patil static int 475*35b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs) 476*35b53f8cSChandrakanth patil { 477*35b53f8cSChandrakanth patil struct hwrm_queue_dscp2pri_qcfg_input req = {0}; 478*35b53f8cSChandrakanth patil struct hwrm_queue_dscp2pri_qcfg_output *resp = 479*35b53f8cSChandrakanth patil (void *)softc->hwrm_cmd_resp.idi_vaddr; 480*35b53f8cSChandrakanth patil struct bnxt_dscp2pri_entry *dscp2pri; 481*35b53f8cSChandrakanth patil struct iflib_dma_info dma_data; 482*35b53f8cSChandrakanth patil int rc, entry_cnt; 483*35b53f8cSChandrakanth patil int i; 484*35b53f8cSChandrakanth patil 485*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10800) 486*35b53f8cSChandrakanth patil return 0; 487*35b53f8cSChandrakanth patil 488*35b53f8cSChandrakanth patil rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri) * 128, &dma_data, 489*35b53f8cSChandrakanth patil BUS_DMA_NOWAIT); 490*35b53f8cSChandrakanth patil if (rc) 491*35b53f8cSChandrakanth patil return ENOMEM; 492*35b53f8cSChandrakanth patil 493*35b53f8cSChandrakanth patil dscp2pri = (void *)dma_data.idi_vaddr; 494*35b53f8cSChandrakanth patil 495*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_QCFG); 496*35b53f8cSChandrakanth patil 497*35b53f8cSChandrakanth patil req.dest_data_addr = htole64(dma_data.idi_paddr); 498*35b53f8cSChandrakanth patil req.dest_data_buffer_size = htole16(sizeof(*dscp2pri) * 64); 499*35b53f8cSChandrakanth patil req.port_id = htole16(softc->pf.port_id); 500*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 501*35b53f8cSChandrakanth patil 502*35b53f8cSChandrakanth patil if (rc) 503*35b53f8cSChandrakanth patil goto end; 504*35b53f8cSChandrakanth patil 505*35b53f8cSChandrakanth patil entry_cnt = le16toh(resp->entry_cnt); 506*35b53f8cSChandrakanth patil for (i = 0; i < entry_cnt; i++) { 507*35b53f8cSChandrakanth patil app[*num_inputs].priority = dscp2pri[i].pri; 508*35b53f8cSChandrakanth patil app[*num_inputs].protocol = dscp2pri[i].dscp; 509*35b53f8cSChandrakanth patil app[*num_inputs].selector = BNXT_IEEE_8021QAZ_APP_SEL_DSCP; 510*35b53f8cSChandrakanth patil (*num_inputs)++; 511*35b53f8cSChandrakanth patil } 512*35b53f8cSChandrakanth patil 513*35b53f8cSChandrakanth patil end: 514*35b53f8cSChandrakanth patil iflib_dma_free(&dma_data); 515*35b53f8cSChandrakanth patil return rc; 516*35b53f8cSChandrakanth patil } 517*35b53f8cSChandrakanth patil 518*35b53f8cSChandrakanth patil static int 519*35b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app, 520*35b53f8cSChandrakanth patil bool add) 521*35b53f8cSChandrakanth patil { 522*35b53f8cSChandrakanth patil struct hwrm_queue_dscp2pri_cfg_input req = {0}; 523*35b53f8cSChandrakanth patil struct bnxt_dscp2pri_entry *dscp2pri; 524*35b53f8cSChandrakanth patil struct iflib_dma_info dma_data; 525*35b53f8cSChandrakanth patil int rc; 526*35b53f8cSChandrakanth patil 527*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10800) 528*35b53f8cSChandrakanth patil return 0; 529*35b53f8cSChandrakanth patil 530*35b53f8cSChandrakanth patil rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri), &dma_data, 531*35b53f8cSChandrakanth patil BUS_DMA_NOWAIT); 532*35b53f8cSChandrakanth patil if (rc) 533*35b53f8cSChandrakanth patil return ENOMEM; 534*35b53f8cSChandrakanth patil 535*35b53f8cSChandrakanth patil bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_CFG); 536*35b53f8cSChandrakanth patil 537*35b53f8cSChandrakanth patil req.src_data_addr = htole64(dma_data.idi_paddr); 538*35b53f8cSChandrakanth patil dscp2pri = (void *)dma_data.idi_vaddr; 539*35b53f8cSChandrakanth patil dscp2pri->dscp = app->protocol; 540*35b53f8cSChandrakanth patil if (add) 541*35b53f8cSChandrakanth patil dscp2pri->mask = 0x3f; 542*35b53f8cSChandrakanth patil else 543*35b53f8cSChandrakanth patil dscp2pri->mask = 0; 544*35b53f8cSChandrakanth patil dscp2pri->pri = app->priority; 545*35b53f8cSChandrakanth patil req.entry_cnt = htole16(1); 546*35b53f8cSChandrakanth patil req.port_id = htole16(softc->pf.port_id); 547*35b53f8cSChandrakanth patil rc = _hwrm_send_message(softc, &req, sizeof(req)); 548*35b53f8cSChandrakanth patil 549*35b53f8cSChandrakanth patil iflib_dma_free(&dma_data); 550*35b53f8cSChandrakanth patil return rc; 551*35b53f8cSChandrakanth patil } 552*35b53f8cSChandrakanth patil 553*35b53f8cSChandrakanth patil static int 554*35b53f8cSChandrakanth patil bnxt_ets_validate(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, uint8_t *tc) 555*35b53f8cSChandrakanth patil { 556*35b53f8cSChandrakanth patil int total_ets_bw = 0; 557*35b53f8cSChandrakanth patil bool zero = false; 558*35b53f8cSChandrakanth patil uint8_t max_tc = 0; 559*35b53f8cSChandrakanth patil int i; 560*35b53f8cSChandrakanth patil 561*35b53f8cSChandrakanth patil for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) { 562*35b53f8cSChandrakanth patil if (ets->prio_tc[i] > softc->max_tc) { 563*35b53f8cSChandrakanth patil device_printf(softc->dev, "priority to TC mapping exceeds TC count %d\n", 564*35b53f8cSChandrakanth patil ets->prio_tc[i]); 565*35b53f8cSChandrakanth patil return -EINVAL; 566*35b53f8cSChandrakanth patil } 567*35b53f8cSChandrakanth patil if (ets->prio_tc[i] > max_tc) 568*35b53f8cSChandrakanth patil max_tc = ets->prio_tc[i]; 569*35b53f8cSChandrakanth patil 570*35b53f8cSChandrakanth patil if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > softc->max_tc) 571*35b53f8cSChandrakanth patil return -EINVAL; 572*35b53f8cSChandrakanth patil 573*35b53f8cSChandrakanth patil switch (ets->tc_tsa[i]) { 574*35b53f8cSChandrakanth patil case BNXT_IEEE_8021QAZ_TSA_STRICT: 575*35b53f8cSChandrakanth patil break; 576*35b53f8cSChandrakanth patil case BNXT_IEEE_8021QAZ_TSA_ETS: 577*35b53f8cSChandrakanth patil total_ets_bw += ets->tc_tx_bw[i]; 578*35b53f8cSChandrakanth patil zero = zero || !ets->tc_tx_bw[i]; 579*35b53f8cSChandrakanth patil break; 580*35b53f8cSChandrakanth patil default: 581*35b53f8cSChandrakanth patil return -ENOTSUPP; 582*35b53f8cSChandrakanth patil } 583*35b53f8cSChandrakanth patil } 584*35b53f8cSChandrakanth patil if (total_ets_bw > 100) { 585*35b53f8cSChandrakanth patil device_printf(softc->dev, "rejecting ETS config exceeding available bandwidth\n"); 586*35b53f8cSChandrakanth patil return -EINVAL; 587*35b53f8cSChandrakanth patil } 588*35b53f8cSChandrakanth patil if (zero && total_ets_bw == 100) { 589*35b53f8cSChandrakanth patil device_printf(softc->dev, "rejecting ETS config starving a TC\n"); 590*35b53f8cSChandrakanth patil return -EINVAL; 591*35b53f8cSChandrakanth patil } 592*35b53f8cSChandrakanth patil 593*35b53f8cSChandrakanth patil if (max_tc >= softc->max_tc) 594*35b53f8cSChandrakanth patil *tc = softc->max_tc; 595*35b53f8cSChandrakanth patil else 596*35b53f8cSChandrakanth patil *tc = max_tc + 1; 597*35b53f8cSChandrakanth patil return 0; 598*35b53f8cSChandrakanth patil } 599*35b53f8cSChandrakanth patil 600*35b53f8cSChandrakanth patil int 601*35b53f8cSChandrakanth patil bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) 602*35b53f8cSChandrakanth patil { 603*35b53f8cSChandrakanth patil struct bnxt_ieee_ets *my_ets = softc->ieee_ets; 604*35b53f8cSChandrakanth patil int rc; 605*35b53f8cSChandrakanth patil 606*35b53f8cSChandrakanth patil if (!my_ets) 607*35b53f8cSChandrakanth patil return 0; 608*35b53f8cSChandrakanth patil 609*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_cos2bw_qcfg(softc, my_ets); 610*35b53f8cSChandrakanth patil if (rc) 611*35b53f8cSChandrakanth patil goto error; 612*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pri2cos_qcfg(softc, my_ets); 613*35b53f8cSChandrakanth patil if (rc) 614*35b53f8cSChandrakanth patil goto error; 615*35b53f8cSChandrakanth patil 616*35b53f8cSChandrakanth patil if (ets) { 617*35b53f8cSChandrakanth patil ets->cbs = my_ets->cbs; 618*35b53f8cSChandrakanth patil ets->ets_cap = softc->max_tc; 619*35b53f8cSChandrakanth patil memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); 620*35b53f8cSChandrakanth patil memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); 621*35b53f8cSChandrakanth patil memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); 622*35b53f8cSChandrakanth patil memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); 623*35b53f8cSChandrakanth patil } 624*35b53f8cSChandrakanth patil return 0; 625*35b53f8cSChandrakanth patil error: 626*35b53f8cSChandrakanth patil return rc; 627*35b53f8cSChandrakanth patil } 628*35b53f8cSChandrakanth patil 629*35b53f8cSChandrakanth patil int 630*35b53f8cSChandrakanth patil bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets) 631*35b53f8cSChandrakanth patil { 632*35b53f8cSChandrakanth patil uint8_t max_tc = 0; 633*35b53f8cSChandrakanth patil int rc; 634*35b53f8cSChandrakanth patil 635*35b53f8cSChandrakanth patil if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || 636*35b53f8cSChandrakanth patil !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) 637*35b53f8cSChandrakanth patil return -EINVAL; 638*35b53f8cSChandrakanth patil 639*35b53f8cSChandrakanth patil rc = bnxt_ets_validate(softc, ets, &max_tc); 640*35b53f8cSChandrakanth patil if (rc) 641*35b53f8cSChandrakanth patil return rc; 642*35b53f8cSChandrakanth patil 643*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_cos2bw_cfg(softc, ets, max_tc); 644*35b53f8cSChandrakanth patil if (rc) 645*35b53f8cSChandrakanth patil goto error; 646*35b53f8cSChandrakanth patil 647*35b53f8cSChandrakanth patil if (!softc->is_asym_q) { 648*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, 649*35b53f8cSChandrakanth patil HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR); 650*35b53f8cSChandrakanth patil if (rc) 651*35b53f8cSChandrakanth patil goto error; 652*35b53f8cSChandrakanth patil } else { 653*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, 654*35b53f8cSChandrakanth patil HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX); 655*35b53f8cSChandrakanth patil if (rc) 656*35b53f8cSChandrakanth patil goto error; 657*35b53f8cSChandrakanth patil 658*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets, 659*35b53f8cSChandrakanth patil HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX); 660*35b53f8cSChandrakanth patil if (rc) 661*35b53f8cSChandrakanth patil goto error; 662*35b53f8cSChandrakanth patil } 663*35b53f8cSChandrakanth patil 664*35b53f8cSChandrakanth patil memcpy(softc->ieee_ets, ets, sizeof(*ets)); 665*35b53f8cSChandrakanth patil return 0; 666*35b53f8cSChandrakanth patil error: 667*35b53f8cSChandrakanth patil return rc; 668*35b53f8cSChandrakanth patil } 669*35b53f8cSChandrakanth patil 670*35b53f8cSChandrakanth patil int 671*35b53f8cSChandrakanth patil bnxt_dcb_ieee_getpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) 672*35b53f8cSChandrakanth patil { 673*35b53f8cSChandrakanth patil struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc; 674*35b53f8cSChandrakanth patil int rc; 675*35b53f8cSChandrakanth patil 676*35b53f8cSChandrakanth patil if (!my_pfc) 677*35b53f8cSChandrakanth patil return -1; 678*35b53f8cSChandrakanth patil 679*35b53f8cSChandrakanth patil pfc->pfc_cap = softc->max_lltc; 680*35b53f8cSChandrakanth patil 681*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pfc_qcfg(softc, my_pfc); 682*35b53f8cSChandrakanth patil if (rc) 683*35b53f8cSChandrakanth patil return 0; 684*35b53f8cSChandrakanth patil 685*35b53f8cSChandrakanth patil pfc->pfc_en = my_pfc->pfc_en; 686*35b53f8cSChandrakanth patil pfc->mbc = my_pfc->mbc; 687*35b53f8cSChandrakanth patil pfc->delay = my_pfc->delay; 688*35b53f8cSChandrakanth patil 689*35b53f8cSChandrakanth patil return 0; 690*35b53f8cSChandrakanth patil } 691*35b53f8cSChandrakanth patil 692*35b53f8cSChandrakanth patil int 693*35b53f8cSChandrakanth patil bnxt_dcb_ieee_setpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc) 694*35b53f8cSChandrakanth patil { 695*35b53f8cSChandrakanth patil struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc; 696*35b53f8cSChandrakanth patil int rc; 697*35b53f8cSChandrakanth patil 698*35b53f8cSChandrakanth patil if (!my_pfc) 699*35b53f8cSChandrakanth patil return -1; 700*35b53f8cSChandrakanth patil 701*35b53f8cSChandrakanth patil if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || 702*35b53f8cSChandrakanth patil !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST) || 703*35b53f8cSChandrakanth patil (softc->phy_flags & BNXT_PHY_FL_NO_PAUSE)) 704*35b53f8cSChandrakanth patil return -EINVAL; 705*35b53f8cSChandrakanth patil 706*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_pfc_cfg(softc, pfc); 707*35b53f8cSChandrakanth patil if (!rc) 708*35b53f8cSChandrakanth patil memcpy(my_pfc, pfc, sizeof(*my_pfc)); 709*35b53f8cSChandrakanth patil 710*35b53f8cSChandrakanth patil return rc; 711*35b53f8cSChandrakanth patil } 712*35b53f8cSChandrakanth patil 713*35b53f8cSChandrakanth patil static int 714*35b53f8cSChandrakanth patil bnxt_dcb_ieee_dscp_app_prep(struct bnxt_softc *softc, struct bnxt_dcb_app *app) 715*35b53f8cSChandrakanth patil { 716*35b53f8cSChandrakanth patil if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) { 717*35b53f8cSChandrakanth patil if (!softc->max_dscp_value) 718*35b53f8cSChandrakanth patil return -ENOTSUPP; 719*35b53f8cSChandrakanth patil if (app->protocol > softc->max_dscp_value) 720*35b53f8cSChandrakanth patil return -EINVAL; 721*35b53f8cSChandrakanth patil } 722*35b53f8cSChandrakanth patil return 0; 723*35b53f8cSChandrakanth patil } 724*35b53f8cSChandrakanth patil 725*35b53f8cSChandrakanth patil int 726*35b53f8cSChandrakanth patil bnxt_dcb_ieee_setapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app) 727*35b53f8cSChandrakanth patil { 728*35b53f8cSChandrakanth patil int rc; 729*35b53f8cSChandrakanth patil 730*35b53f8cSChandrakanth patil 731*35b53f8cSChandrakanth patil if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || 732*35b53f8cSChandrakanth patil !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) 733*35b53f8cSChandrakanth patil return -EINVAL; 734*35b53f8cSChandrakanth patil 735*35b53f8cSChandrakanth patil rc = bnxt_dcb_ieee_dscp_app_prep(softc, app); 736*35b53f8cSChandrakanth patil if (rc) 737*35b53f8cSChandrakanth patil return rc; 738*35b53f8cSChandrakanth patil 739*35b53f8cSChandrakanth patil if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE && 740*35b53f8cSChandrakanth patil app->protocol == ETH_P_ROCE) || 741*35b53f8cSChandrakanth patil (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM && 742*35b53f8cSChandrakanth patil app->protocol == ROCE_V2_UDP_DPORT)) 743*35b53f8cSChandrakanth patil rc = bnxt_hwrm_set_dcbx_app(softc, app, true); 744*35b53f8cSChandrakanth patil 745*35b53f8cSChandrakanth patil if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) 746*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, true); 747*35b53f8cSChandrakanth patil 748*35b53f8cSChandrakanth patil return rc; 749*35b53f8cSChandrakanth patil } 750*35b53f8cSChandrakanth patil 751*35b53f8cSChandrakanth patil int 752*35b53f8cSChandrakanth patil bnxt_dcb_ieee_delapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app) 753*35b53f8cSChandrakanth patil { 754*35b53f8cSChandrakanth patil int rc; 755*35b53f8cSChandrakanth patil 756*35b53f8cSChandrakanth patil if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) || 757*35b53f8cSChandrakanth patil !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST)) 758*35b53f8cSChandrakanth patil return -EINVAL; 759*35b53f8cSChandrakanth patil 760*35b53f8cSChandrakanth patil rc = bnxt_dcb_ieee_dscp_app_prep(softc, app); 761*35b53f8cSChandrakanth patil if (rc) 762*35b53f8cSChandrakanth patil return rc; 763*35b53f8cSChandrakanth patil 764*35b53f8cSChandrakanth patil if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE && 765*35b53f8cSChandrakanth patil app->protocol == ETH_P_ROCE) || 766*35b53f8cSChandrakanth patil (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM && 767*35b53f8cSChandrakanth patil app->protocol == ROCE_V2_UDP_DPORT)) 768*35b53f8cSChandrakanth patil rc = bnxt_hwrm_set_dcbx_app(softc, app, false); 769*35b53f8cSChandrakanth patil 770*35b53f8cSChandrakanth patil if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) 771*35b53f8cSChandrakanth patil rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, false); 772*35b53f8cSChandrakanth patil 773*35b53f8cSChandrakanth patil return rc; 774*35b53f8cSChandrakanth patil } 775*35b53f8cSChandrakanth patil 776*35b53f8cSChandrakanth patil int 777*35b53f8cSChandrakanth patil bnxt_dcb_ieee_listapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app, int *num_inputs) 778*35b53f8cSChandrakanth patil { 779*35b53f8cSChandrakanth patil bnxt_hwrm_get_dcbx_app(softc, app, num_inputs); 780*35b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp2pri_qcfg(softc, app, num_inputs); 781*35b53f8cSChandrakanth patil 782*35b53f8cSChandrakanth patil return 0; 783*35b53f8cSChandrakanth patil } 784*35b53f8cSChandrakanth patil 785*35b53f8cSChandrakanth patil uint8_t 786*35b53f8cSChandrakanth patil bnxt_dcb_getdcbx(struct bnxt_softc *softc) 787*35b53f8cSChandrakanth patil { 788*35b53f8cSChandrakanth patil return softc->dcbx_cap; 789*35b53f8cSChandrakanth patil } 790*35b53f8cSChandrakanth patil 791*35b53f8cSChandrakanth patil uint8_t 792*35b53f8cSChandrakanth patil bnxt_dcb_setdcbx(struct bnxt_softc *softc, uint8_t mode) 793*35b53f8cSChandrakanth patil { 794*35b53f8cSChandrakanth patil /* All firmware DCBX settings are set in NVRAM */ 795*35b53f8cSChandrakanth patil if (softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED) 796*35b53f8cSChandrakanth patil return 1; 797*35b53f8cSChandrakanth patil 798*35b53f8cSChandrakanth patil /* 799*35b53f8cSChandrakanth patil * Do't allow editing CAP_DCBX_LLD_MANAGED since it is driven 800*35b53f8cSChandrakanth patil * based on FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED 801*35b53f8cSChandrakanth patil */ 802*35b53f8cSChandrakanth patil if ((softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED) != 803*35b53f8cSChandrakanth patil (mode & BNXT_DCB_CAP_DCBX_LLD_MANAGED)) 804*35b53f8cSChandrakanth patil return 1; 805*35b53f8cSChandrakanth patil 806*35b53f8cSChandrakanth patil if (mode & BNXT_DCB_CAP_DCBX_HOST) { 807*35b53f8cSChandrakanth patil if (BNXT_VF(softc) || (softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 808*35b53f8cSChandrakanth patil return 1; 809*35b53f8cSChandrakanth patil 810*35b53f8cSChandrakanth patil /* only support BNXT_IEEE */ 811*35b53f8cSChandrakanth patil if ((mode & BNXT_DCB_CAP_DCBX_VER_CEE) || 812*35b53f8cSChandrakanth patil !(mode & BNXT_DCB_CAP_DCBX_VER_IEEE)) 813*35b53f8cSChandrakanth patil return 1; 814*35b53f8cSChandrakanth patil } 815*35b53f8cSChandrakanth patil 816*35b53f8cSChandrakanth patil if (mode == softc->dcbx_cap) 817*35b53f8cSChandrakanth patil return 0; 818*35b53f8cSChandrakanth patil 819*35b53f8cSChandrakanth patil softc->dcbx_cap = mode; 820*35b53f8cSChandrakanth patil return 0; 821*35b53f8cSChandrakanth patil } 822*35b53f8cSChandrakanth patil 823*35b53f8cSChandrakanth patil void 824*35b53f8cSChandrakanth patil bnxt_dcb_init(struct bnxt_softc *softc) 825*35b53f8cSChandrakanth patil { 826*35b53f8cSChandrakanth patil struct bnxt_ieee_ets ets = {0}; 827*35b53f8cSChandrakanth patil struct bnxt_ieee_pfc pfc = {0}; 828*35b53f8cSChandrakanth patil 829*35b53f8cSChandrakanth patil softc->dcbx_cap = 0; 830*35b53f8cSChandrakanth patil 831*35b53f8cSChandrakanth patil if (softc->hwrm_spec_code < 0x10501) 832*35b53f8cSChandrakanth patil return; 833*35b53f8cSChandrakanth patil 834*35b53f8cSChandrakanth patil softc->ieee_ets = malloc(sizeof(struct bnxt_ieee_ets), M_DEVBUF, M_NOWAIT | M_ZERO); 835*35b53f8cSChandrakanth patil if (!softc->ieee_ets) 836*35b53f8cSChandrakanth patil return; 837*35b53f8cSChandrakanth patil 838*35b53f8cSChandrakanth patil softc->ieee_pfc = malloc(sizeof(struct bnxt_ieee_pfc), M_DEVBUF, M_NOWAIT | M_ZERO); 839*35b53f8cSChandrakanth patil if (!softc->ieee_pfc) 840*35b53f8cSChandrakanth patil return; 841*35b53f8cSChandrakanth patil 842*35b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp_qcaps(softc); 843*35b53f8cSChandrakanth patil softc->dcbx_cap = BNXT_DCB_CAP_DCBX_VER_IEEE; 844*35b53f8cSChandrakanth patil if (BNXT_PF(softc) && !(softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 845*35b53f8cSChandrakanth patil softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_HOST; 846*35b53f8cSChandrakanth patil else if (softc->fw_cap & BNXT_FW_CAP_DCBX_AGENT) 847*35b53f8cSChandrakanth patil softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_LLD_MANAGED; 848*35b53f8cSChandrakanth patil 849*35b53f8cSChandrakanth patil bnxt_dcb_ieee_setets(softc, &ets); 850*35b53f8cSChandrakanth patil bnxt_dcb_ieee_setpfc(softc, &pfc); 851*35b53f8cSChandrakanth patil 852*35b53f8cSChandrakanth patil } 853*35b53f8cSChandrakanth patil 854*35b53f8cSChandrakanth patil void 855*35b53f8cSChandrakanth patil bnxt_dcb_free(struct bnxt_softc *softc) 856*35b53f8cSChandrakanth patil { 857*35b53f8cSChandrakanth patil free(softc->ieee_ets, M_DEVBUF); 858*35b53f8cSChandrakanth patil softc->ieee_ets = NULL; 859*35b53f8cSChandrakanth patil free(softc->ieee_pfc, M_DEVBUF); 860*35b53f8cSChandrakanth patil softc->ieee_pfc = NULL; 861*35b53f8cSChandrakanth patil } 862