xref: /freebsd/sys/dev/bnxt/bnxt_en/bnxt_dcb.c (revision 3de231b4d956f7b9c22e31f75805030a417f7bf3)
135b53f8cSChandrakanth patil /*-
235b53f8cSChandrakanth patil  * Broadcom NetXtreme-C/E network driver.
335b53f8cSChandrakanth patil  *
435b53f8cSChandrakanth patil  * Copyright (c) 2024 Broadcom, All Rights Reserved.
535b53f8cSChandrakanth patil  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
635b53f8cSChandrakanth patil  *
735b53f8cSChandrakanth patil  * Redistribution and use in source and binary forms, with or without
835b53f8cSChandrakanth patil  * modification, are permitted provided that the following conditions
935b53f8cSChandrakanth patil  * are met:
1035b53f8cSChandrakanth patil  * 1. Redistributions of source code must retain the above copyright
1135b53f8cSChandrakanth patil  *    notice, this list of conditions and the following disclaimer.
1235b53f8cSChandrakanth patil  * 2. Redistributions in binary form must reproduce the above copyright
1335b53f8cSChandrakanth patil  *    notice, this list of conditions and the following disclaimer in the
1435b53f8cSChandrakanth patil  *    documentation and/or other materials provided with the distribution.
1535b53f8cSChandrakanth patil  *
1635b53f8cSChandrakanth patil  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
1735b53f8cSChandrakanth patil  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1835b53f8cSChandrakanth patil  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1935b53f8cSChandrakanth patil  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
2035b53f8cSChandrakanth patil  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2135b53f8cSChandrakanth patil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2235b53f8cSChandrakanth patil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2335b53f8cSChandrakanth patil  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2435b53f8cSChandrakanth patil  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2535b53f8cSChandrakanth patil  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2635b53f8cSChandrakanth patil  * THE POSSIBILITY OF SUCH DAMAGE.
2735b53f8cSChandrakanth patil  */
2835b53f8cSChandrakanth patil 
2935b53f8cSChandrakanth patil #include <sys/endian.h>
3035b53f8cSChandrakanth patil #include <linux/errno.h>
3135b53f8cSChandrakanth patil #include <linux/bitops.h>
3235b53f8cSChandrakanth patil 
3335b53f8cSChandrakanth patil #include "bnxt.h"
3435b53f8cSChandrakanth patil #include "bnxt_hwrm.h"
3535b53f8cSChandrakanth patil #include "bnxt_dcb.h"
3635b53f8cSChandrakanth patil #include "hsi_struct_def.h"
3735b53f8cSChandrakanth patil 
3835b53f8cSChandrakanth patil static int
bnxt_tx_queue_to_tc(struct bnxt_softc * softc,uint8_t queue_id)3935b53f8cSChandrakanth patil bnxt_tx_queue_to_tc(struct bnxt_softc *softc, uint8_t queue_id)
4035b53f8cSChandrakanth patil {
4135b53f8cSChandrakanth patil 	int i, j;
4235b53f8cSChandrakanth patil 
4335b53f8cSChandrakanth patil 	for (i = 0; i < softc->max_tc; i++) {
4435b53f8cSChandrakanth patil 		if (softc->tx_q_info[i].queue_id == queue_id) {
4535b53f8cSChandrakanth patil 			for (j = 0; j < softc->max_tc; j++) {
4635b53f8cSChandrakanth patil 				if (softc->tc_to_qidx[j] == i)
4735b53f8cSChandrakanth patil 					return j;
4835b53f8cSChandrakanth patil 			}
4935b53f8cSChandrakanth patil 		}
5035b53f8cSChandrakanth patil 	}
5135b53f8cSChandrakanth patil 	return -EINVAL;
5235b53f8cSChandrakanth patil }
5335b53f8cSChandrakanth patil 
5435b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets,uint32_t path_dir)5535b53f8cSChandrakanth patil bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc *softc,
5635b53f8cSChandrakanth patil 				       struct bnxt_ieee_ets *ets,
5735b53f8cSChandrakanth patil 				       uint32_t path_dir)
5835b53f8cSChandrakanth patil {
5935b53f8cSChandrakanth patil 	struct hwrm_queue_pri2cos_cfg_input req = {0};
6035b53f8cSChandrakanth patil 	struct bnxt_queue_info *q_info;
6135b53f8cSChandrakanth patil 	uint8_t *pri2cos;
6235b53f8cSChandrakanth patil 	int i;
6335b53f8cSChandrakanth patil 
6435b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_CFG);
6535b53f8cSChandrakanth patil 
6635b53f8cSChandrakanth patil 	req.flags = htole32(path_dir | HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN);
6735b53f8cSChandrakanth patil 	if (path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR ||
6835b53f8cSChandrakanth patil 	    path_dir == HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX)
6935b53f8cSChandrakanth patil 		q_info = softc->tx_q_info;
7035b53f8cSChandrakanth patil 	else
7135b53f8cSChandrakanth patil 		q_info = softc->rx_q_info;
7235b53f8cSChandrakanth patil 	pri2cos = &req.pri0_cos_queue_id;
7335b53f8cSChandrakanth patil 	for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) {
7435b53f8cSChandrakanth patil 		uint8_t qidx;
7535b53f8cSChandrakanth patil 
7635b53f8cSChandrakanth patil 		req.enables |= htole32(HWRM_QUEUE_PRI2COS_CFG_INPUT_ENABLES_PRI0_COS_QUEUE_ID << i);
7735b53f8cSChandrakanth patil 
7835b53f8cSChandrakanth patil 		qidx = softc->tc_to_qidx[ets->prio_tc[i]];
7935b53f8cSChandrakanth patil 		pri2cos[i] = q_info[qidx].queue_id;
8035b53f8cSChandrakanth patil 	}
8135b53f8cSChandrakanth patil 	return _hwrm_send_message(softc, &req, sizeof(req));
8235b53f8cSChandrakanth patil }
8335b53f8cSChandrakanth patil 
8435b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets)8535b53f8cSChandrakanth patil bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
8635b53f8cSChandrakanth patil {
8735b53f8cSChandrakanth patil 	struct hwrm_queue_pri2cos_qcfg_output *resp =
8835b53f8cSChandrakanth patil 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
8935b53f8cSChandrakanth patil 	struct hwrm_queue_pri2cos_qcfg_input req = {0};
9035b53f8cSChandrakanth patil 	int rc;
9135b53f8cSChandrakanth patil 
9235b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG);
9335b53f8cSChandrakanth patil 
9435b53f8cSChandrakanth patil 	req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN);
9535b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
9635b53f8cSChandrakanth patil 	if (!rc) {
9735b53f8cSChandrakanth patil 		uint8_t *pri2cos = &resp->pri0_cos_queue_id;
9835b53f8cSChandrakanth patil 		int i;
9935b53f8cSChandrakanth patil 
10035b53f8cSChandrakanth patil 		for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) {
10135b53f8cSChandrakanth patil 			uint8_t queue_id = pri2cos[i];
10235b53f8cSChandrakanth patil 			int tc;
10335b53f8cSChandrakanth patil 
10435b53f8cSChandrakanth patil 			tc = bnxt_tx_queue_to_tc(softc, queue_id);
10535b53f8cSChandrakanth patil 			if (tc >= 0)
10635b53f8cSChandrakanth patil 				ets->prio_tc[i] = tc;
10735b53f8cSChandrakanth patil 		}
10835b53f8cSChandrakanth patil 	}
10935b53f8cSChandrakanth patil 	return rc;
11035b53f8cSChandrakanth patil }
11135b53f8cSChandrakanth patil 
11235b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets,uint8_t max_tc)11335b53f8cSChandrakanth patil bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets,
11435b53f8cSChandrakanth patil 				      uint8_t max_tc)
11535b53f8cSChandrakanth patil {
11635b53f8cSChandrakanth patil 	struct hwrm_queue_cos2bw_cfg_input req = {0};
11735b53f8cSChandrakanth patil 	struct bnxt_cos2bw_cfg cos2bw;
11835b53f8cSChandrakanth patil 	void *data;
11935b53f8cSChandrakanth patil 	int i;
12035b53f8cSChandrakanth patil 
12135b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_CFG);
12235b53f8cSChandrakanth patil 
12335b53f8cSChandrakanth patil 	for (i = 0; i < max_tc; i++) {
12435b53f8cSChandrakanth patil 		uint8_t qidx = softc->tc_to_qidx[i];
12535b53f8cSChandrakanth patil 
12635b53f8cSChandrakanth patil 		req.enables |=
12735b53f8cSChandrakanth patil 			htole32(HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID << qidx);
12835b53f8cSChandrakanth patil 
12935b53f8cSChandrakanth patil 		memset(&cos2bw, 0, sizeof(cos2bw));
13035b53f8cSChandrakanth patil 		cos2bw.queue_id = softc->tx_q_info[qidx].queue_id;
13135b53f8cSChandrakanth patil 		if (ets->tc_tsa[i] == BNXT_IEEE_8021QAZ_TSA_STRICT) {
13235b53f8cSChandrakanth patil 			cos2bw.tsa =
13335b53f8cSChandrakanth patil 				HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP;
13435b53f8cSChandrakanth patil 			cos2bw.pri_lvl = i;
13535b53f8cSChandrakanth patil 		} else {
13635b53f8cSChandrakanth patil 			cos2bw.tsa =
13735b53f8cSChandrakanth patil 				HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS;
13835b53f8cSChandrakanth patil 			cos2bw.bw_weight = ets->tc_tx_bw[i];
13935b53f8cSChandrakanth patil 			/* older firmware requires min_bw to be set to the
14035b53f8cSChandrakanth patil 			 * same weight value in percent.
14135b53f8cSChandrakanth patil 			 */
14235b53f8cSChandrakanth patil 			if (BNXT_FW_MAJ(softc) < 218) {
14335b53f8cSChandrakanth patil 				cos2bw.min_bw =
14435b53f8cSChandrakanth patil 					htole32((ets->tc_tx_bw[i] * 100) |
14535b53f8cSChandrakanth patil 						    BW_VALUE_UNIT_PERCENT1_100);
14635b53f8cSChandrakanth patil 			}
14735b53f8cSChandrakanth patil 		}
14835b53f8cSChandrakanth patil 		data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4);
14935b53f8cSChandrakanth patil 		memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
15035b53f8cSChandrakanth patil 		if (qidx == 0) {
15135b53f8cSChandrakanth patil 			req.queue_id0 = cos2bw.queue_id;
15235b53f8cSChandrakanth patil 			req.unused_0 = 0;
15335b53f8cSChandrakanth patil 		}
15435b53f8cSChandrakanth patil 	}
15535b53f8cSChandrakanth patil 	return _hwrm_send_message(softc, &req, sizeof(req));
15635b53f8cSChandrakanth patil }
15735b53f8cSChandrakanth patil 
15835b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets)15935b53f8cSChandrakanth patil bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
16035b53f8cSChandrakanth patil {
16135b53f8cSChandrakanth patil 	struct hwrm_queue_cos2bw_qcfg_output *resp =
16235b53f8cSChandrakanth patil 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
16335b53f8cSChandrakanth patil 	struct hwrm_queue_cos2bw_qcfg_input req = {0};
16435b53f8cSChandrakanth patil 	struct bnxt_cos2bw_cfg cos2bw;
16535b53f8cSChandrakanth patil 	uint8_t *data;
16635b53f8cSChandrakanth patil 	int rc, i;
16735b53f8cSChandrakanth patil 
16835b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_QCFG);
16935b53f8cSChandrakanth patil 
17035b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
17135b53f8cSChandrakanth patil 	if (rc) {
17235b53f8cSChandrakanth patil 		return rc;
17335b53f8cSChandrakanth patil 	}
17435b53f8cSChandrakanth patil 
17535b53f8cSChandrakanth patil 	data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
17635b53f8cSChandrakanth patil 	for (i = 0; i < softc->max_tc; i++, data += sizeof(cos2bw.cfg)) {
17735b53f8cSChandrakanth patil 		int tc;
17835b53f8cSChandrakanth patil 
17935b53f8cSChandrakanth patil 		memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg));
18035b53f8cSChandrakanth patil 		if (i == 0)
18135b53f8cSChandrakanth patil 			cos2bw.queue_id = resp->queue_id0;
18235b53f8cSChandrakanth patil 
18335b53f8cSChandrakanth patil 		tc = bnxt_tx_queue_to_tc(softc, cos2bw.queue_id);
18435b53f8cSChandrakanth patil 		if (tc < 0)
18535b53f8cSChandrakanth patil 			continue;
18635b53f8cSChandrakanth patil 
18735b53f8cSChandrakanth patil 		if (cos2bw.tsa == HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP) {
18835b53f8cSChandrakanth patil 			ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_STRICT;
18935b53f8cSChandrakanth patil 		} else {
19035b53f8cSChandrakanth patil 			ets->tc_tsa[tc] = BNXT_IEEE_8021QAZ_TSA_ETS;
19135b53f8cSChandrakanth patil 			ets->tc_tx_bw[tc] = cos2bw.bw_weight;
19235b53f8cSChandrakanth patil 		}
19335b53f8cSChandrakanth patil 	}
19435b53f8cSChandrakanth patil 	return 0;
19535b53f8cSChandrakanth patil }
19635b53f8cSChandrakanth patil 
19735b53f8cSChandrakanth patil static int
bnxt_queue_remap(struct bnxt_softc * softc,unsigned int lltc_mask)19835b53f8cSChandrakanth patil bnxt_queue_remap(struct bnxt_softc *softc, unsigned int lltc_mask)
19935b53f8cSChandrakanth patil {
20035b53f8cSChandrakanth patil 	unsigned long qmap = 0;
20135b53f8cSChandrakanth patil 	int max = softc->max_tc;
20235b53f8cSChandrakanth patil 	int i, j, rc;
20335b53f8cSChandrakanth patil 
20435b53f8cSChandrakanth patil 	/* Assign lossless TCs first */
20535b53f8cSChandrakanth patil 	for (i = 0, j = 0; i < max; ) {
20635b53f8cSChandrakanth patil 		if (lltc_mask & (1 << i)) {
20735b53f8cSChandrakanth patil 			if (BNXT_LLQ(softc->rx_q_info[j].queue_profile)) {
20835b53f8cSChandrakanth patil 				softc->tc_to_qidx[i] = j;
20935b53f8cSChandrakanth patil 				__set_bit(j, &qmap);
21035b53f8cSChandrakanth patil 				i++;
21135b53f8cSChandrakanth patil 			}
21235b53f8cSChandrakanth patil 			j++;
21335b53f8cSChandrakanth patil 			continue;
21435b53f8cSChandrakanth patil 		}
21535b53f8cSChandrakanth patil 		i++;
21635b53f8cSChandrakanth patil 	}
21735b53f8cSChandrakanth patil 
21835b53f8cSChandrakanth patil 	for (i = 0, j = 0; i < max; i++) {
21935b53f8cSChandrakanth patil 		if (lltc_mask & (1 << i))
22035b53f8cSChandrakanth patil 			continue;
22135b53f8cSChandrakanth patil 		j = find_next_zero_bit(&qmap, max, j);
22235b53f8cSChandrakanth patil 		softc->tc_to_qidx[i] = j;
22335b53f8cSChandrakanth patil 		__set_bit(j, &qmap);
22435b53f8cSChandrakanth patil 		j++;
22535b53f8cSChandrakanth patil 	}
22635b53f8cSChandrakanth patil 
22735b53f8cSChandrakanth patil 	if (softc->ieee_ets) {
22835b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_cos2bw_cfg(softc, softc->ieee_ets, softc->max_tc);
22935b53f8cSChandrakanth patil 		if (rc) {
23035b53f8cSChandrakanth patil 			device_printf(softc->dev, "failed to config BW, rc = %d\n", rc);
23135b53f8cSChandrakanth patil 			return rc;
23235b53f8cSChandrakanth patil 		}
23335b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_pri2cos_cfg(softc, softc->ieee_ets,
23435b53f8cSChandrakanth patil 						 HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR);
23535b53f8cSChandrakanth patil 		if (rc) {
23635b53f8cSChandrakanth patil 			device_printf(softc->dev, "failed to config prio, rc = %d\n", rc);
23735b53f8cSChandrakanth patil 			return rc;
23835b53f8cSChandrakanth patil 		}
23935b53f8cSChandrakanth patil 	}
24035b53f8cSChandrakanth patil 	return 0;
24135b53f8cSChandrakanth patil }
24235b53f8cSChandrakanth patil 
24335b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc * softc,struct bnxt_ieee_pfc * pfc)24435b53f8cSChandrakanth patil bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
24535b53f8cSChandrakanth patil {
24635b53f8cSChandrakanth patil 	struct hwrm_queue_pfcenable_cfg_input req = {0};
24735b53f8cSChandrakanth patil 	struct bnxt_ieee_ets *my_ets = softc->ieee_ets;
24835b53f8cSChandrakanth patil 	unsigned int tc_mask = 0, pri_mask = 0;
24935b53f8cSChandrakanth patil 	uint8_t i, pri, lltc_count = 0;
25035b53f8cSChandrakanth patil 	bool need_q_remap = false;
25135b53f8cSChandrakanth patil 
25235b53f8cSChandrakanth patil 	if (!my_ets)
25335b53f8cSChandrakanth patil 		return -EINVAL;
25435b53f8cSChandrakanth patil 
25535b53f8cSChandrakanth patil 	for (i = 0; i < softc->max_tc; i++) {
25635b53f8cSChandrakanth patil 		for (pri = 0; pri < BNXT_IEEE_8021QAZ_MAX_TCS; pri++) {
25735b53f8cSChandrakanth patil 			if ((pfc->pfc_en & (1 << pri)) &&
25835b53f8cSChandrakanth patil 			    (my_ets->prio_tc[pri] == i)) {
25935b53f8cSChandrakanth patil 				pri_mask |= 1 << pri;
26035b53f8cSChandrakanth patil 				tc_mask |= 1 << i;
26135b53f8cSChandrakanth patil 			}
26235b53f8cSChandrakanth patil 		}
26335b53f8cSChandrakanth patil 		if (tc_mask & (1 << i))
26435b53f8cSChandrakanth patil 			lltc_count++;
26535b53f8cSChandrakanth patil 	}
26635b53f8cSChandrakanth patil 
26735b53f8cSChandrakanth patil 	if (lltc_count > softc->max_lltc) {
26835b53f8cSChandrakanth patil 		device_printf(softc->dev,
26935b53f8cSChandrakanth patil 			       "Hardware doesn't support %d lossless queues "
27035b53f8cSChandrakanth patil 			       "to configure PFC (cap %d)\n", lltc_count, softc->max_lltc);
27135b53f8cSChandrakanth patil 		return -EINVAL;
27235b53f8cSChandrakanth patil 	}
27335b53f8cSChandrakanth patil 
27435b53f8cSChandrakanth patil 	for (i = 0; i < softc->max_tc; i++) {
27535b53f8cSChandrakanth patil 		if (tc_mask & (1 << i)) {
27635b53f8cSChandrakanth patil 			uint8_t qidx = softc->tc_to_qidx[i];
27735b53f8cSChandrakanth patil 
27835b53f8cSChandrakanth patil 			if (!BNXT_LLQ(softc->rx_q_info[qidx].queue_profile)) {
27935b53f8cSChandrakanth patil 				need_q_remap = true;
28035b53f8cSChandrakanth patil 				break;
28135b53f8cSChandrakanth patil 			}
28235b53f8cSChandrakanth patil 		}
28335b53f8cSChandrakanth patil 	}
28435b53f8cSChandrakanth patil 
28535b53f8cSChandrakanth patil 	if (need_q_remap)
28635b53f8cSChandrakanth patil 		bnxt_queue_remap(softc, tc_mask);
28735b53f8cSChandrakanth patil 
28835b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_CFG);
28935b53f8cSChandrakanth patil 
29035b53f8cSChandrakanth patil 	req.flags = htole32(pri_mask);
29135b53f8cSChandrakanth patil 	return _hwrm_send_message(softc, &req, sizeof(req));
29235b53f8cSChandrakanth patil }
29335b53f8cSChandrakanth patil 
29435b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc * softc,struct bnxt_ieee_pfc * pfc)29535b53f8cSChandrakanth patil bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
29635b53f8cSChandrakanth patil {
29735b53f8cSChandrakanth patil 	struct hwrm_queue_pfcenable_qcfg_output *resp =
29835b53f8cSChandrakanth patil 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
29935b53f8cSChandrakanth patil 	struct hwrm_queue_pfcenable_qcfg_input req = {0};
30035b53f8cSChandrakanth patil 	uint8_t pri_mask;
30135b53f8cSChandrakanth patil 	int rc;
30235b53f8cSChandrakanth patil 
30335b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_QCFG);
30435b53f8cSChandrakanth patil 
30535b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
30635b53f8cSChandrakanth patil 	if (rc) {
30735b53f8cSChandrakanth patil 		return rc;
30835b53f8cSChandrakanth patil 	}
30935b53f8cSChandrakanth patil 
31035b53f8cSChandrakanth patil 	pri_mask = le32toh(resp->flags);
31135b53f8cSChandrakanth patil 	pfc->pfc_en = pri_mask;
31235b53f8cSChandrakanth patil 	return 0;
31335b53f8cSChandrakanth patil }
31435b53f8cSChandrakanth patil 
31535b53f8cSChandrakanth patil static int
bnxt_hwrm_get_dcbx_app(struct bnxt_softc * softc,struct bnxt_dcb_app * app,size_t nitems,int * num_inputs)316*3de231b4SZhenlei Huang bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
317*3de231b4SZhenlei Huang     size_t nitems, int *num_inputs)
31835b53f8cSChandrakanth patil {
31935b53f8cSChandrakanth patil 	struct hwrm_fw_get_structured_data_input get = {0};
32035b53f8cSChandrakanth patil 	struct hwrm_struct_data_dcbx_app *fw_app;
32135b53f8cSChandrakanth patil 	struct hwrm_struct_hdr *data;
32235b53f8cSChandrakanth patil 	struct iflib_dma_info dma_data;
32335b53f8cSChandrakanth patil 	size_t data_len;
32435b53f8cSChandrakanth patil 	int rc, n, i;
32535b53f8cSChandrakanth patil 
32635b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10601)
32735b53f8cSChandrakanth patil 		return 0;
32835b53f8cSChandrakanth patil 
32935b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA);
33035b53f8cSChandrakanth patil 
33135b53f8cSChandrakanth patil 	n = BNXT_IEEE_8021QAZ_MAX_TCS;
33235b53f8cSChandrakanth patil 	data_len = sizeof(*data) + sizeof(*fw_app) * n;
33335b53f8cSChandrakanth patil 	rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data,
33435b53f8cSChandrakanth patil 			     BUS_DMA_NOWAIT);
33535b53f8cSChandrakanth patil 	if (rc)
33635b53f8cSChandrakanth patil 		return ENOMEM;
33735b53f8cSChandrakanth patil 	get.dest_data_addr = htole64(dma_data.idi_paddr);
33835b53f8cSChandrakanth patil 	get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP);
33935b53f8cSChandrakanth patil 	get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
34035b53f8cSChandrakanth patil 	get.count = 0;
34135b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &get, sizeof(get));
34235b53f8cSChandrakanth patil 	if (rc)
34335b53f8cSChandrakanth patil 		goto set_app_exit;
34435b53f8cSChandrakanth patil 
34535b53f8cSChandrakanth patil 	data = (void *)dma_data.idi_vaddr;
34635b53f8cSChandrakanth patil 	fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1);
34735b53f8cSChandrakanth patil 
34835b53f8cSChandrakanth patil 	if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) {
34935b53f8cSChandrakanth patil 		rc = -ENODEV;
35035b53f8cSChandrakanth patil 		goto set_app_exit;
35135b53f8cSChandrakanth patil 	}
35235b53f8cSChandrakanth patil 
35335b53f8cSChandrakanth patil 	n = data->count;
354*3de231b4SZhenlei Huang 	for (i = 0; i < n && *num_inputs < nitems; i++, fw_app++) {
35535b53f8cSChandrakanth patil 		app[*num_inputs].priority = fw_app->priority;
35635b53f8cSChandrakanth patil 		app[*num_inputs].protocol = htobe16(fw_app->protocol_id);
35735b53f8cSChandrakanth patil 		app[*num_inputs].selector = fw_app->protocol_selector;
35835b53f8cSChandrakanth patil 		(*num_inputs)++;
35935b53f8cSChandrakanth patil 	}
36035b53f8cSChandrakanth patil 
36135b53f8cSChandrakanth patil set_app_exit:
36235b53f8cSChandrakanth patil 	iflib_dma_free(&dma_data);
36335b53f8cSChandrakanth patil 	return rc;
36435b53f8cSChandrakanth patil }
36535b53f8cSChandrakanth patil 
36635b53f8cSChandrakanth patil static int
bnxt_hwrm_set_dcbx_app(struct bnxt_softc * softc,struct bnxt_dcb_app * app,bool add)36735b53f8cSChandrakanth patil bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
36835b53f8cSChandrakanth patil 				  bool add)
36935b53f8cSChandrakanth patil {
37035b53f8cSChandrakanth patil 	struct hwrm_fw_set_structured_data_input set = {0};
37135b53f8cSChandrakanth patil 	struct hwrm_fw_get_structured_data_input get = {0};
37235b53f8cSChandrakanth patil 	struct hwrm_struct_data_dcbx_app *fw_app;
37335b53f8cSChandrakanth patil 	struct hwrm_struct_hdr *data;
37435b53f8cSChandrakanth patil 	struct iflib_dma_info dma_data;
37535b53f8cSChandrakanth patil 	size_t data_len;
37635b53f8cSChandrakanth patil 	int rc, n, i;
37735b53f8cSChandrakanth patil 
37835b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10601)
37935b53f8cSChandrakanth patil 		return 0;
38035b53f8cSChandrakanth patil 
38135b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &get, HWRM_FW_GET_STRUCTURED_DATA);
38235b53f8cSChandrakanth patil 
38335b53f8cSChandrakanth patil 	n = BNXT_IEEE_8021QAZ_MAX_TCS;
38435b53f8cSChandrakanth patil 	data_len = sizeof(*data) + sizeof(*fw_app) * n;
38535b53f8cSChandrakanth patil 	rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data,
38635b53f8cSChandrakanth patil 			     BUS_DMA_NOWAIT);
38735b53f8cSChandrakanth patil 	if (rc)
38835b53f8cSChandrakanth patil 		return ENOMEM;
38935b53f8cSChandrakanth patil 	get.dest_data_addr = htole64(dma_data.idi_paddr);
39035b53f8cSChandrakanth patil 	get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP);
39135b53f8cSChandrakanth patil 	get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
39235b53f8cSChandrakanth patil 	get.count = 0;
39335b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &get, sizeof(get));
39435b53f8cSChandrakanth patil 	if (rc)
39535b53f8cSChandrakanth patil 		goto set_app_exit;
39635b53f8cSChandrakanth patil 
39735b53f8cSChandrakanth patil 	data = (void *)dma_data.idi_vaddr;
39835b53f8cSChandrakanth patil 	fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1);
39935b53f8cSChandrakanth patil 
40035b53f8cSChandrakanth patil 	if (data->struct_id != htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP)) {
40135b53f8cSChandrakanth patil 		rc = -ENODEV;
40235b53f8cSChandrakanth patil 		goto set_app_exit;
40335b53f8cSChandrakanth patil 	}
40435b53f8cSChandrakanth patil 
40535b53f8cSChandrakanth patil 	n = data->count;
40635b53f8cSChandrakanth patil 	for (i = 0; i < n; i++, fw_app++) {
40735b53f8cSChandrakanth patil 		if (fw_app->protocol_id == htobe16(app->protocol) &&
40835b53f8cSChandrakanth patil 		    fw_app->protocol_selector == app->selector &&
40935b53f8cSChandrakanth patil 		    fw_app->priority == app->priority) {
41035b53f8cSChandrakanth patil 			if (add)
41135b53f8cSChandrakanth patil 				goto set_app_exit;
41235b53f8cSChandrakanth patil 			else
41335b53f8cSChandrakanth patil 				break;
41435b53f8cSChandrakanth patil 		}
41535b53f8cSChandrakanth patil 	}
41635b53f8cSChandrakanth patil 	if (add) {
41735b53f8cSChandrakanth patil 		/* append */
41835b53f8cSChandrakanth patil 		n++;
41935b53f8cSChandrakanth patil 		fw_app->protocol_id = htobe16(app->protocol);
42035b53f8cSChandrakanth patil 		fw_app->protocol_selector = app->selector;
42135b53f8cSChandrakanth patil 		fw_app->priority = app->priority;
42235b53f8cSChandrakanth patil 		fw_app->valid = 1;
42335b53f8cSChandrakanth patil 	} else {
42435b53f8cSChandrakanth patil 		size_t len = 0;
42535b53f8cSChandrakanth patil 
42635b53f8cSChandrakanth patil 		/* not found, nothing to delete */
42735b53f8cSChandrakanth patil 		if (n == i)
42835b53f8cSChandrakanth patil 			goto set_app_exit;
42935b53f8cSChandrakanth patil 
43035b53f8cSChandrakanth patil 		len = (n - 1 - i) * sizeof(*fw_app);
43135b53f8cSChandrakanth patil 		if (len)
43235b53f8cSChandrakanth patil 			memmove(fw_app, fw_app + 1, len);
43335b53f8cSChandrakanth patil 		n--;
43435b53f8cSChandrakanth patil 		memset(fw_app + n, 0, sizeof(*fw_app));
43535b53f8cSChandrakanth patil 	}
43635b53f8cSChandrakanth patil 	data->count = n;
43735b53f8cSChandrakanth patil 	data->len = htole16(sizeof(*fw_app) * n);
43835b53f8cSChandrakanth patil 	data->subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
43935b53f8cSChandrakanth patil 
44035b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &set, HWRM_FW_SET_STRUCTURED_DATA);
44135b53f8cSChandrakanth patil 
44235b53f8cSChandrakanth patil 	set.src_data_addr = htole64(dma_data.idi_paddr);
44335b53f8cSChandrakanth patil 	set.data_len = htole16(sizeof(*data) + sizeof(*fw_app) * n);
44435b53f8cSChandrakanth patil 	set.hdr_cnt = 1;
44535b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &set, sizeof(set));
44635b53f8cSChandrakanth patil 
44735b53f8cSChandrakanth patil set_app_exit:
44835b53f8cSChandrakanth patil 	iflib_dma_free(&dma_data);
44935b53f8cSChandrakanth patil 	return rc;
45035b53f8cSChandrakanth patil }
45135b53f8cSChandrakanth patil 
45235b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc * softc)45335b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc *softc)
45435b53f8cSChandrakanth patil {
45535b53f8cSChandrakanth patil 	struct hwrm_queue_dscp_qcaps_output *resp =
45635b53f8cSChandrakanth patil 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
45735b53f8cSChandrakanth patil 	struct hwrm_queue_dscp_qcaps_input req = {0};
45835b53f8cSChandrakanth patil 	int rc;
45935b53f8cSChandrakanth patil 
46035b53f8cSChandrakanth patil 	softc->max_dscp_value = 0;
46135b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10800 || BNXT_VF(softc))
46235b53f8cSChandrakanth patil 		return 0;
46335b53f8cSChandrakanth patil 
46435b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP_QCAPS);
46535b53f8cSChandrakanth patil 
46635b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
46735b53f8cSChandrakanth patil 	if (!rc) {
46835b53f8cSChandrakanth patil 		softc->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
46935b53f8cSChandrakanth patil 		if (softc->max_dscp_value < 0x3f)
47035b53f8cSChandrakanth patil 			softc->max_dscp_value = 0;
47135b53f8cSChandrakanth patil 	}
47235b53f8cSChandrakanth patil 	return rc;
47335b53f8cSChandrakanth patil }
47435b53f8cSChandrakanth patil 
47535b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc * softc,struct bnxt_dcb_app * app,size_t nitems,int * num_inputs)476*3de231b4SZhenlei Huang bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
477*3de231b4SZhenlei Huang     size_t nitems, int *num_inputs)
47835b53f8cSChandrakanth patil {
47935b53f8cSChandrakanth patil 	struct hwrm_queue_dscp2pri_qcfg_input req = {0};
48035b53f8cSChandrakanth patil 	struct hwrm_queue_dscp2pri_qcfg_output *resp =
48135b53f8cSChandrakanth patil 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
48235b53f8cSChandrakanth patil 	struct bnxt_dscp2pri_entry *dscp2pri;
48335b53f8cSChandrakanth patil 	struct iflib_dma_info dma_data;
48435b53f8cSChandrakanth patil 	int rc, entry_cnt;
48535b53f8cSChandrakanth patil 	int i;
48635b53f8cSChandrakanth patil 
48735b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10800)
48835b53f8cSChandrakanth patil 		return 0;
48935b53f8cSChandrakanth patil 
49035b53f8cSChandrakanth patil 	rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri) * 128, &dma_data,
49135b53f8cSChandrakanth patil 			     BUS_DMA_NOWAIT);
49235b53f8cSChandrakanth patil 	if (rc)
49335b53f8cSChandrakanth patil 		return ENOMEM;
49435b53f8cSChandrakanth patil 
49535b53f8cSChandrakanth patil 	dscp2pri = (void *)dma_data.idi_vaddr;
49635b53f8cSChandrakanth patil 
49735b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_QCFG);
49835b53f8cSChandrakanth patil 
49935b53f8cSChandrakanth patil 	req.dest_data_addr = htole64(dma_data.idi_paddr);
50035b53f8cSChandrakanth patil 	req.dest_data_buffer_size = htole16(sizeof(*dscp2pri) * 64);
50135b53f8cSChandrakanth patil 	req.port_id = htole16(softc->pf.port_id);
50235b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
50335b53f8cSChandrakanth patil 
50435b53f8cSChandrakanth patil 	if (rc)
50535b53f8cSChandrakanth patil 		goto end;
50635b53f8cSChandrakanth patil 
50735b53f8cSChandrakanth patil 	entry_cnt =  le16toh(resp->entry_cnt);
508*3de231b4SZhenlei Huang 	for (i = 0; i < entry_cnt && *num_inputs < nitems; i++) {
50935b53f8cSChandrakanth patil 		app[*num_inputs].priority = dscp2pri[i].pri;
51035b53f8cSChandrakanth patil 		app[*num_inputs].protocol = dscp2pri[i].dscp;
51135b53f8cSChandrakanth patil 		app[*num_inputs].selector = BNXT_IEEE_8021QAZ_APP_SEL_DSCP;
51235b53f8cSChandrakanth patil 		(*num_inputs)++;
51335b53f8cSChandrakanth patil 	}
51435b53f8cSChandrakanth patil 
51535b53f8cSChandrakanth patil end:
51635b53f8cSChandrakanth patil 	iflib_dma_free(&dma_data);
51735b53f8cSChandrakanth patil 	return rc;
51835b53f8cSChandrakanth patil }
51935b53f8cSChandrakanth patil 
52035b53f8cSChandrakanth patil static int
bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc * softc,struct bnxt_dcb_app * app,bool add)52135b53f8cSChandrakanth patil bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
52235b53f8cSChandrakanth patil 			     bool add)
52335b53f8cSChandrakanth patil {
52435b53f8cSChandrakanth patil 	struct hwrm_queue_dscp2pri_cfg_input req = {0};
52535b53f8cSChandrakanth patil 	struct bnxt_dscp2pri_entry *dscp2pri;
52635b53f8cSChandrakanth patil 	struct iflib_dma_info dma_data;
52735b53f8cSChandrakanth patil 	int rc;
52835b53f8cSChandrakanth patil 
52935b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10800)
53035b53f8cSChandrakanth patil 		return 0;
53135b53f8cSChandrakanth patil 
53235b53f8cSChandrakanth patil 	rc = iflib_dma_alloc(softc->ctx, sizeof(*dscp2pri), &dma_data,
53335b53f8cSChandrakanth patil 			     BUS_DMA_NOWAIT);
53435b53f8cSChandrakanth patil 	if (rc)
53535b53f8cSChandrakanth patil 		return ENOMEM;
53635b53f8cSChandrakanth patil 
53735b53f8cSChandrakanth patil 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP2PRI_CFG);
53835b53f8cSChandrakanth patil 
53935b53f8cSChandrakanth patil 	req.src_data_addr = htole64(dma_data.idi_paddr);
54035b53f8cSChandrakanth patil 	dscp2pri = (void *)dma_data.idi_vaddr;
54135b53f8cSChandrakanth patil 	dscp2pri->dscp = app->protocol;
54235b53f8cSChandrakanth patil 	if (add)
54335b53f8cSChandrakanth patil 		dscp2pri->mask = 0x3f;
54435b53f8cSChandrakanth patil 	else
54535b53f8cSChandrakanth patil 		dscp2pri->mask = 0;
54635b53f8cSChandrakanth patil 	dscp2pri->pri = app->priority;
54735b53f8cSChandrakanth patil 	req.entry_cnt = htole16(1);
54835b53f8cSChandrakanth patil 	req.port_id = htole16(softc->pf.port_id);
54935b53f8cSChandrakanth patil 	rc = _hwrm_send_message(softc, &req, sizeof(req));
55035b53f8cSChandrakanth patil 
55135b53f8cSChandrakanth patil 	iflib_dma_free(&dma_data);
55235b53f8cSChandrakanth patil 	return rc;
55335b53f8cSChandrakanth patil }
55435b53f8cSChandrakanth patil 
55535b53f8cSChandrakanth patil static int
bnxt_ets_validate(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets,uint8_t * tc)55635b53f8cSChandrakanth patil bnxt_ets_validate(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets, uint8_t *tc)
55735b53f8cSChandrakanth patil {
55835b53f8cSChandrakanth patil 	int total_ets_bw = 0;
55935b53f8cSChandrakanth patil 	bool zero = false;
56035b53f8cSChandrakanth patil 	uint8_t max_tc = 0;
56135b53f8cSChandrakanth patil 	int i;
56235b53f8cSChandrakanth patil 
56335b53f8cSChandrakanth patil 	for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) {
56435b53f8cSChandrakanth patil 		if (ets->prio_tc[i] > softc->max_tc) {
56535b53f8cSChandrakanth patil 			device_printf(softc->dev, "priority to TC mapping exceeds TC count %d\n",
56635b53f8cSChandrakanth patil 				   ets->prio_tc[i]);
56735b53f8cSChandrakanth patil 			return -EINVAL;
56835b53f8cSChandrakanth patil 		}
56935b53f8cSChandrakanth patil 		if (ets->prio_tc[i] > max_tc)
57035b53f8cSChandrakanth patil 			max_tc = ets->prio_tc[i];
57135b53f8cSChandrakanth patil 
57235b53f8cSChandrakanth patil 		if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > softc->max_tc)
57335b53f8cSChandrakanth patil 			return -EINVAL;
57435b53f8cSChandrakanth patil 
57535b53f8cSChandrakanth patil 		switch (ets->tc_tsa[i]) {
57635b53f8cSChandrakanth patil 		case BNXT_IEEE_8021QAZ_TSA_STRICT:
57735b53f8cSChandrakanth patil 			break;
57835b53f8cSChandrakanth patil 		case BNXT_IEEE_8021QAZ_TSA_ETS:
57935b53f8cSChandrakanth patil 			total_ets_bw += ets->tc_tx_bw[i];
58035b53f8cSChandrakanth patil 			zero = zero || !ets->tc_tx_bw[i];
58135b53f8cSChandrakanth patil 			break;
58235b53f8cSChandrakanth patil 		default:
58335b53f8cSChandrakanth patil 			return -ENOTSUPP;
58435b53f8cSChandrakanth patil 		}
58535b53f8cSChandrakanth patil 	}
58635b53f8cSChandrakanth patil 	if (total_ets_bw > 100) {
58735b53f8cSChandrakanth patil 		device_printf(softc->dev, "rejecting ETS config exceeding available bandwidth\n");
58835b53f8cSChandrakanth patil 		return -EINVAL;
58935b53f8cSChandrakanth patil 	}
59035b53f8cSChandrakanth patil 	if (zero && total_ets_bw == 100) {
59135b53f8cSChandrakanth patil 		device_printf(softc->dev, "rejecting ETS config starving a TC\n");
59235b53f8cSChandrakanth patil 		return -EINVAL;
59335b53f8cSChandrakanth patil 	}
59435b53f8cSChandrakanth patil 
59535b53f8cSChandrakanth patil 	if (max_tc >= softc->max_tc)
59635b53f8cSChandrakanth patil 		*tc = softc->max_tc;
59735b53f8cSChandrakanth patil 	else
59835b53f8cSChandrakanth patil 		*tc = max_tc + 1;
59935b53f8cSChandrakanth patil 	return 0;
60035b53f8cSChandrakanth patil }
60135b53f8cSChandrakanth patil 
60235b53f8cSChandrakanth patil int
bnxt_dcb_ieee_getets(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets)60335b53f8cSChandrakanth patil bnxt_dcb_ieee_getets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
60435b53f8cSChandrakanth patil {
60535b53f8cSChandrakanth patil 	struct bnxt_ieee_ets *my_ets = softc->ieee_ets;
60635b53f8cSChandrakanth patil 	int rc;
60735b53f8cSChandrakanth patil 
60835b53f8cSChandrakanth patil 	if (!my_ets)
60935b53f8cSChandrakanth patil 		return 0;
61035b53f8cSChandrakanth patil 
61135b53f8cSChandrakanth patil 	rc = bnxt_hwrm_queue_cos2bw_qcfg(softc, my_ets);
61235b53f8cSChandrakanth patil 	if (rc)
61335b53f8cSChandrakanth patil 		goto error;
61435b53f8cSChandrakanth patil 	rc = bnxt_hwrm_queue_pri2cos_qcfg(softc, my_ets);
61535b53f8cSChandrakanth patil 	if (rc)
61635b53f8cSChandrakanth patil 		goto error;
61735b53f8cSChandrakanth patil 
61835b53f8cSChandrakanth patil 	if (ets) {
61935b53f8cSChandrakanth patil 		ets->cbs = my_ets->cbs;
62035b53f8cSChandrakanth patil 		ets->ets_cap = softc->max_tc;
62135b53f8cSChandrakanth patil 		memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
62235b53f8cSChandrakanth patil 		memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
62335b53f8cSChandrakanth patil 		memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
62435b53f8cSChandrakanth patil 		memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
62535b53f8cSChandrakanth patil 	}
62635b53f8cSChandrakanth patil 	return 0;
62735b53f8cSChandrakanth patil error:
62835b53f8cSChandrakanth patil 	return rc;
62935b53f8cSChandrakanth patil }
63035b53f8cSChandrakanth patil 
63135b53f8cSChandrakanth patil int
bnxt_dcb_ieee_setets(struct bnxt_softc * softc,struct bnxt_ieee_ets * ets)63235b53f8cSChandrakanth patil bnxt_dcb_ieee_setets(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
63335b53f8cSChandrakanth patil {
63435b53f8cSChandrakanth patil 	uint8_t max_tc = 0;
63535b53f8cSChandrakanth patil 	int rc;
63635b53f8cSChandrakanth patil 
63735b53f8cSChandrakanth patil 	if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) ||
63835b53f8cSChandrakanth patil 	    !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST))
63935b53f8cSChandrakanth patil 		return -EINVAL;
64035b53f8cSChandrakanth patil 
64135b53f8cSChandrakanth patil 	rc = bnxt_ets_validate(softc, ets, &max_tc);
64235b53f8cSChandrakanth patil 	if (rc)
64335b53f8cSChandrakanth patil 		return rc;
64435b53f8cSChandrakanth patil 
64535b53f8cSChandrakanth patil 	rc = bnxt_hwrm_queue_cos2bw_cfg(softc, ets, max_tc);
64635b53f8cSChandrakanth patil 	if (rc)
64735b53f8cSChandrakanth patil 		goto error;
64835b53f8cSChandrakanth patil 
64935b53f8cSChandrakanth patil 	if (!softc->is_asym_q) {
65035b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets,
65135b53f8cSChandrakanth patil 						 HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_BIDIR);
65235b53f8cSChandrakanth patil 		if (rc)
65335b53f8cSChandrakanth patil 			goto error;
65435b53f8cSChandrakanth patil 	} else {
65535b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets,
65635b53f8cSChandrakanth patil 						 HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX);
65735b53f8cSChandrakanth patil 		if (rc)
65835b53f8cSChandrakanth patil 			goto error;
65935b53f8cSChandrakanth patil 
66035b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_pri2cos_cfg(softc, ets,
66135b53f8cSChandrakanth patil 						 HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX);
66235b53f8cSChandrakanth patil 		if (rc)
66335b53f8cSChandrakanth patil 			goto error;
66435b53f8cSChandrakanth patil 	}
66535b53f8cSChandrakanth patil 
66635b53f8cSChandrakanth patil 	memcpy(softc->ieee_ets, ets, sizeof(*ets));
66735b53f8cSChandrakanth patil 	return 0;
66835b53f8cSChandrakanth patil error:
66935b53f8cSChandrakanth patil 	return rc;
67035b53f8cSChandrakanth patil }
67135b53f8cSChandrakanth patil 
67235b53f8cSChandrakanth patil int
bnxt_dcb_ieee_getpfc(struct bnxt_softc * softc,struct bnxt_ieee_pfc * pfc)67335b53f8cSChandrakanth patil bnxt_dcb_ieee_getpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
67435b53f8cSChandrakanth patil {
67535b53f8cSChandrakanth patil 	struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc;
67635b53f8cSChandrakanth patil 	int rc;
67735b53f8cSChandrakanth patil 
67835b53f8cSChandrakanth patil 	if (!my_pfc)
67935b53f8cSChandrakanth patil 		return -1;
68035b53f8cSChandrakanth patil 
68135b53f8cSChandrakanth patil 	pfc->pfc_cap = softc->max_lltc;
68235b53f8cSChandrakanth patil 
68335b53f8cSChandrakanth patil 	rc = bnxt_hwrm_queue_pfc_qcfg(softc, my_pfc);
68435b53f8cSChandrakanth patil 	if (rc)
68535b53f8cSChandrakanth patil 		return 0;
68635b53f8cSChandrakanth patil 
68735b53f8cSChandrakanth patil 	pfc->pfc_en = my_pfc->pfc_en;
68835b53f8cSChandrakanth patil 	pfc->mbc = my_pfc->mbc;
68935b53f8cSChandrakanth patil 	pfc->delay = my_pfc->delay;
69035b53f8cSChandrakanth patil 
69135b53f8cSChandrakanth patil 	return 0;
69235b53f8cSChandrakanth patil }
69335b53f8cSChandrakanth patil 
69435b53f8cSChandrakanth patil int
bnxt_dcb_ieee_setpfc(struct bnxt_softc * softc,struct bnxt_ieee_pfc * pfc)69535b53f8cSChandrakanth patil bnxt_dcb_ieee_setpfc(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
69635b53f8cSChandrakanth patil {
69735b53f8cSChandrakanth patil 	struct bnxt_ieee_pfc *my_pfc = softc->ieee_pfc;
69835b53f8cSChandrakanth patil 	int rc;
69935b53f8cSChandrakanth patil 
70035b53f8cSChandrakanth patil 	if (!my_pfc)
70135b53f8cSChandrakanth patil 		return -1;
70235b53f8cSChandrakanth patil 
70335b53f8cSChandrakanth patil 	if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) ||
70435b53f8cSChandrakanth patil 	    !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST) ||
70535b53f8cSChandrakanth patil 	    (softc->phy_flags & BNXT_PHY_FL_NO_PAUSE))
70635b53f8cSChandrakanth patil 		return -EINVAL;
70735b53f8cSChandrakanth patil 
70835b53f8cSChandrakanth patil 	rc = bnxt_hwrm_queue_pfc_cfg(softc, pfc);
70935b53f8cSChandrakanth patil 	if (!rc)
71035b53f8cSChandrakanth patil 		memcpy(my_pfc, pfc, sizeof(*my_pfc));
71135b53f8cSChandrakanth patil 
71235b53f8cSChandrakanth patil 	return rc;
71335b53f8cSChandrakanth patil }
71435b53f8cSChandrakanth patil 
71535b53f8cSChandrakanth patil static int
bnxt_dcb_ieee_dscp_app_prep(struct bnxt_softc * softc,struct bnxt_dcb_app * app)71635b53f8cSChandrakanth patil bnxt_dcb_ieee_dscp_app_prep(struct bnxt_softc *softc, struct bnxt_dcb_app *app)
71735b53f8cSChandrakanth patil {
71835b53f8cSChandrakanth patil 	if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP) {
71935b53f8cSChandrakanth patil 		if (!softc->max_dscp_value)
72035b53f8cSChandrakanth patil 			return -ENOTSUPP;
72135b53f8cSChandrakanth patil 		if (app->protocol > softc->max_dscp_value)
72235b53f8cSChandrakanth patil 			return -EINVAL;
72335b53f8cSChandrakanth patil 	}
72435b53f8cSChandrakanth patil 	return 0;
72535b53f8cSChandrakanth patil }
72635b53f8cSChandrakanth patil 
72735b53f8cSChandrakanth patil int
bnxt_dcb_ieee_setapp(struct bnxt_softc * softc,struct bnxt_dcb_app * app)72835b53f8cSChandrakanth patil bnxt_dcb_ieee_setapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app)
72935b53f8cSChandrakanth patil {
73035b53f8cSChandrakanth patil 	int rc;
73135b53f8cSChandrakanth patil 
73235b53f8cSChandrakanth patil 
73335b53f8cSChandrakanth patil 	if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) ||
73435b53f8cSChandrakanth patil 	    !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST))
73535b53f8cSChandrakanth patil 		return -EINVAL;
73635b53f8cSChandrakanth patil 
73735b53f8cSChandrakanth patil 	rc = bnxt_dcb_ieee_dscp_app_prep(softc, app);
73835b53f8cSChandrakanth patil 	if (rc)
73935b53f8cSChandrakanth patil 		return rc;
74035b53f8cSChandrakanth patil 
74135b53f8cSChandrakanth patil 	if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
74235b53f8cSChandrakanth patil 	     app->protocol == ETH_P_ROCE) ||
74335b53f8cSChandrakanth patil 	    (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM &&
74435b53f8cSChandrakanth patil 	     app->protocol == ROCE_V2_UDP_DPORT))
74535b53f8cSChandrakanth patil 		rc = bnxt_hwrm_set_dcbx_app(softc, app, true);
74635b53f8cSChandrakanth patil 
74735b53f8cSChandrakanth patil 	if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP)
74835b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, true);
74935b53f8cSChandrakanth patil 
75035b53f8cSChandrakanth patil 	return rc;
75135b53f8cSChandrakanth patil }
75235b53f8cSChandrakanth patil 
75335b53f8cSChandrakanth patil int
bnxt_dcb_ieee_delapp(struct bnxt_softc * softc,struct bnxt_dcb_app * app)75435b53f8cSChandrakanth patil bnxt_dcb_ieee_delapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app)
75535b53f8cSChandrakanth patil {
75635b53f8cSChandrakanth patil 	int rc;
75735b53f8cSChandrakanth patil 
75835b53f8cSChandrakanth patil 	if (!(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_VER_IEEE) ||
75935b53f8cSChandrakanth patil 	    !(softc->dcbx_cap & BNXT_DCB_CAP_DCBX_HOST))
76035b53f8cSChandrakanth patil 		return -EINVAL;
76135b53f8cSChandrakanth patil 
76235b53f8cSChandrakanth patil 	rc = bnxt_dcb_ieee_dscp_app_prep(softc, app);
76335b53f8cSChandrakanth patil 	if (rc)
76435b53f8cSChandrakanth patil 		return rc;
76535b53f8cSChandrakanth patil 
76635b53f8cSChandrakanth patil 	if ((app->selector == BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
76735b53f8cSChandrakanth patil 	     app->protocol == ETH_P_ROCE) ||
76835b53f8cSChandrakanth patil 	    (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DGRAM &&
76935b53f8cSChandrakanth patil 	     app->protocol == ROCE_V2_UDP_DPORT))
77035b53f8cSChandrakanth patil 		rc = bnxt_hwrm_set_dcbx_app(softc, app, false);
77135b53f8cSChandrakanth patil 
77235b53f8cSChandrakanth patil 	if (app->selector == BNXT_IEEE_8021QAZ_APP_SEL_DSCP)
77335b53f8cSChandrakanth patil 		rc = bnxt_hwrm_queue_dscp2pri_cfg(softc, app, false);
77435b53f8cSChandrakanth patil 
77535b53f8cSChandrakanth patil 	return rc;
77635b53f8cSChandrakanth patil }
77735b53f8cSChandrakanth patil 
77835b53f8cSChandrakanth patil int
bnxt_dcb_ieee_listapp(struct bnxt_softc * softc,struct bnxt_dcb_app * app,size_t nitems,int * num_inputs)779*3de231b4SZhenlei Huang bnxt_dcb_ieee_listapp(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
780*3de231b4SZhenlei Huang     size_t nitems, int *num_inputs)
78135b53f8cSChandrakanth patil {
782*3de231b4SZhenlei Huang 	bnxt_hwrm_get_dcbx_app(softc, app, nitems, num_inputs);
783*3de231b4SZhenlei Huang 	bnxt_hwrm_queue_dscp2pri_qcfg(softc, app, nitems, num_inputs);
78435b53f8cSChandrakanth patil 
78535b53f8cSChandrakanth patil 	return 0;
78635b53f8cSChandrakanth patil }
78735b53f8cSChandrakanth patil 
78835b53f8cSChandrakanth patil uint8_t
bnxt_dcb_getdcbx(struct bnxt_softc * softc)78935b53f8cSChandrakanth patil bnxt_dcb_getdcbx(struct bnxt_softc *softc)
79035b53f8cSChandrakanth patil {
79135b53f8cSChandrakanth patil 	return softc->dcbx_cap;
79235b53f8cSChandrakanth patil }
79335b53f8cSChandrakanth patil 
79435b53f8cSChandrakanth patil uint8_t
bnxt_dcb_setdcbx(struct bnxt_softc * softc,uint8_t mode)79535b53f8cSChandrakanth patil bnxt_dcb_setdcbx(struct bnxt_softc *softc, uint8_t mode)
79635b53f8cSChandrakanth patil {
79735b53f8cSChandrakanth patil 	/* All firmware DCBX settings are set in NVRAM */
79835b53f8cSChandrakanth patil 	if (softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED)
79935b53f8cSChandrakanth patil 		return 1;
80035b53f8cSChandrakanth patil 
80135b53f8cSChandrakanth patil 	/*
80235b53f8cSChandrakanth patil 	 * Do't allow editing CAP_DCBX_LLD_MANAGED since it is driven
80335b53f8cSChandrakanth patil 	 * based on FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED
80435b53f8cSChandrakanth patil 	 */
80535b53f8cSChandrakanth patil 	if ((softc->dcbx_cap & BNXT_DCB_CAP_DCBX_LLD_MANAGED) !=
80635b53f8cSChandrakanth patil 	    (mode & BNXT_DCB_CAP_DCBX_LLD_MANAGED))
80735b53f8cSChandrakanth patil 		return 1;
80835b53f8cSChandrakanth patil 
80935b53f8cSChandrakanth patil 	if (mode & BNXT_DCB_CAP_DCBX_HOST) {
81035b53f8cSChandrakanth patil 		if (BNXT_VF(softc) || (softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
81135b53f8cSChandrakanth patil 			return 1;
81235b53f8cSChandrakanth patil 
81335b53f8cSChandrakanth patil 		/* only support BNXT_IEEE */
81435b53f8cSChandrakanth patil 		if ((mode & BNXT_DCB_CAP_DCBX_VER_CEE) ||
81535b53f8cSChandrakanth patil 		    !(mode & BNXT_DCB_CAP_DCBX_VER_IEEE))
81635b53f8cSChandrakanth patil 			return 1;
81735b53f8cSChandrakanth patil 	}
81835b53f8cSChandrakanth patil 
81935b53f8cSChandrakanth patil 	if (mode == softc->dcbx_cap)
82035b53f8cSChandrakanth patil 		return 0;
82135b53f8cSChandrakanth patil 
82235b53f8cSChandrakanth patil 	softc->dcbx_cap = mode;
82335b53f8cSChandrakanth patil 	return 0;
82435b53f8cSChandrakanth patil }
82535b53f8cSChandrakanth patil 
82635b53f8cSChandrakanth patil void
bnxt_dcb_init(struct bnxt_softc * softc)82735b53f8cSChandrakanth patil bnxt_dcb_init(struct bnxt_softc *softc)
82835b53f8cSChandrakanth patil {
82935b53f8cSChandrakanth patil 	struct bnxt_ieee_ets ets = {0};
83035b53f8cSChandrakanth patil 	struct bnxt_ieee_pfc pfc = {0};
83135b53f8cSChandrakanth patil 
83235b53f8cSChandrakanth patil 	softc->dcbx_cap = 0;
83335b53f8cSChandrakanth patil 
83435b53f8cSChandrakanth patil 	if (softc->hwrm_spec_code < 0x10501)
83535b53f8cSChandrakanth patil 		return;
83635b53f8cSChandrakanth patil 
83735b53f8cSChandrakanth patil 	softc->ieee_ets = malloc(sizeof(struct bnxt_ieee_ets), M_DEVBUF, M_NOWAIT | M_ZERO);
83835b53f8cSChandrakanth patil 	if (!softc->ieee_ets)
83935b53f8cSChandrakanth patil 		return;
84035b53f8cSChandrakanth patil 
84135b53f8cSChandrakanth patil 	softc->ieee_pfc = malloc(sizeof(struct bnxt_ieee_pfc), M_DEVBUF, M_NOWAIT | M_ZERO);
84235b53f8cSChandrakanth patil 	if (!softc->ieee_pfc)
84335b53f8cSChandrakanth patil 		return;
84435b53f8cSChandrakanth patil 
84535b53f8cSChandrakanth patil 	bnxt_hwrm_queue_dscp_qcaps(softc);
84635b53f8cSChandrakanth patil 	softc->dcbx_cap = BNXT_DCB_CAP_DCBX_VER_IEEE;
84735b53f8cSChandrakanth patil 	if (BNXT_PF(softc) && !(softc->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
84835b53f8cSChandrakanth patil 		softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_HOST;
84935b53f8cSChandrakanth patil 	else if (softc->fw_cap & BNXT_FW_CAP_DCBX_AGENT)
85035b53f8cSChandrakanth patil 		softc->dcbx_cap |= BNXT_DCB_CAP_DCBX_LLD_MANAGED;
85135b53f8cSChandrakanth patil 
85235b53f8cSChandrakanth patil 	bnxt_dcb_ieee_setets(softc, &ets);
85335b53f8cSChandrakanth patil 	bnxt_dcb_ieee_setpfc(softc, &pfc);
85435b53f8cSChandrakanth patil 
85535b53f8cSChandrakanth patil }
85635b53f8cSChandrakanth patil 
85735b53f8cSChandrakanth patil void
bnxt_dcb_free(struct bnxt_softc * softc)85835b53f8cSChandrakanth patil bnxt_dcb_free(struct bnxt_softc *softc)
85935b53f8cSChandrakanth patil {
86035b53f8cSChandrakanth patil 	free(softc->ieee_ets, M_DEVBUF);
86135b53f8cSChandrakanth patil 	softc->ieee_ets = NULL;
86235b53f8cSChandrakanth patil 	free(softc->ieee_pfc, M_DEVBUF);
86335b53f8cSChandrakanth patil 	softc->ieee_pfc = NULL;
86435b53f8cSChandrakanth patil }
865