xref: /freebsd/sys/dev/bnxt/bnxt_en/bnxt_dcb.c (revision 35b53f8c989f62286aad075ef2e97bba358144f8)
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