xref: /freebsd/sys/dev/ixl/i40e_dcb.c (revision ceebc2f348c028b21bf9bcc99f7a3c4b0cb7d926)
1*ceebc2f3SEric Joyner /******************************************************************************
2*ceebc2f3SEric Joyner 
3*ceebc2f3SEric Joyner   Copyright (c) 2013-2017, Intel Corporation
4*ceebc2f3SEric Joyner   All rights reserved.
5*ceebc2f3SEric Joyner 
6*ceebc2f3SEric Joyner   Redistribution and use in source and binary forms, with or without
7*ceebc2f3SEric Joyner   modification, are permitted provided that the following conditions are met:
8*ceebc2f3SEric Joyner 
9*ceebc2f3SEric Joyner    1. Redistributions of source code must retain the above copyright notice,
10*ceebc2f3SEric Joyner       this list of conditions and the following disclaimer.
11*ceebc2f3SEric Joyner 
12*ceebc2f3SEric Joyner    2. Redistributions in binary form must reproduce the above copyright
13*ceebc2f3SEric Joyner       notice, this list of conditions and the following disclaimer in the
14*ceebc2f3SEric Joyner       documentation and/or other materials provided with the distribution.
15*ceebc2f3SEric Joyner 
16*ceebc2f3SEric Joyner    3. Neither the name of the Intel Corporation nor the names of its
17*ceebc2f3SEric Joyner       contributors may be used to endorse or promote products derived from
18*ceebc2f3SEric Joyner       this software without specific prior written permission.
19*ceebc2f3SEric Joyner 
20*ceebc2f3SEric Joyner   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21*ceebc2f3SEric Joyner   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*ceebc2f3SEric Joyner   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*ceebc2f3SEric Joyner   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24*ceebc2f3SEric Joyner   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*ceebc2f3SEric Joyner   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*ceebc2f3SEric Joyner   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*ceebc2f3SEric Joyner   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*ceebc2f3SEric Joyner   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*ceebc2f3SEric Joyner   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*ceebc2f3SEric Joyner   POSSIBILITY OF SUCH DAMAGE.
31*ceebc2f3SEric Joyner 
32*ceebc2f3SEric Joyner ******************************************************************************/
33*ceebc2f3SEric Joyner /*$FreeBSD$*/
34*ceebc2f3SEric Joyner 
35*ceebc2f3SEric Joyner #include "i40e_adminq.h"
36*ceebc2f3SEric Joyner #include "i40e_prototype.h"
37*ceebc2f3SEric Joyner #include "i40e_dcb.h"
38*ceebc2f3SEric Joyner 
39*ceebc2f3SEric Joyner /**
40*ceebc2f3SEric Joyner  * i40e_get_dcbx_status
41*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
42*ceebc2f3SEric Joyner  * @status: Embedded DCBX Engine Status
43*ceebc2f3SEric Joyner  *
44*ceebc2f3SEric Joyner  * Get the DCBX status from the Firmware
45*ceebc2f3SEric Joyner  **/
46*ceebc2f3SEric Joyner enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
47*ceebc2f3SEric Joyner {
48*ceebc2f3SEric Joyner 	u32 reg;
49*ceebc2f3SEric Joyner 
50*ceebc2f3SEric Joyner 	if (!status)
51*ceebc2f3SEric Joyner 		return I40E_ERR_PARAM;
52*ceebc2f3SEric Joyner 
53*ceebc2f3SEric Joyner 	reg = rd32(hw, I40E_PRTDCB_GENS);
54*ceebc2f3SEric Joyner 	*status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
55*ceebc2f3SEric Joyner 			I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
56*ceebc2f3SEric Joyner 
57*ceebc2f3SEric Joyner 	return I40E_SUCCESS;
58*ceebc2f3SEric Joyner }
59*ceebc2f3SEric Joyner 
60*ceebc2f3SEric Joyner /**
61*ceebc2f3SEric Joyner  * i40e_parse_ieee_etscfg_tlv
62*ceebc2f3SEric Joyner  * @tlv: IEEE 802.1Qaz ETS CFG TLV
63*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update ETS CFG data
64*ceebc2f3SEric Joyner  *
65*ceebc2f3SEric Joyner  * Parses IEEE 802.1Qaz ETS CFG TLV
66*ceebc2f3SEric Joyner  **/
67*ceebc2f3SEric Joyner static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
68*ceebc2f3SEric Joyner 				       struct i40e_dcbx_config *dcbcfg)
69*ceebc2f3SEric Joyner {
70*ceebc2f3SEric Joyner 	struct i40e_dcb_ets_config *etscfg;
71*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
72*ceebc2f3SEric Joyner 	u16 offset = 0;
73*ceebc2f3SEric Joyner 	u8 priority;
74*ceebc2f3SEric Joyner 	int i;
75*ceebc2f3SEric Joyner 
76*ceebc2f3SEric Joyner 	/* First Octet post subtype
77*ceebc2f3SEric Joyner 	 * --------------------------
78*ceebc2f3SEric Joyner 	 * |will-|CBS  | Re-  | Max |
79*ceebc2f3SEric Joyner 	 * |ing  |     |served| TCs |
80*ceebc2f3SEric Joyner 	 * --------------------------
81*ceebc2f3SEric Joyner 	 * |1bit | 1bit|3 bits|3bits|
82*ceebc2f3SEric Joyner 	 */
83*ceebc2f3SEric Joyner 	etscfg = &dcbcfg->etscfg;
84*ceebc2f3SEric Joyner 	etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
85*ceebc2f3SEric Joyner 			       I40E_IEEE_ETS_WILLING_SHIFT);
86*ceebc2f3SEric Joyner 	etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
87*ceebc2f3SEric Joyner 			   I40E_IEEE_ETS_CBS_SHIFT);
88*ceebc2f3SEric Joyner 	etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
89*ceebc2f3SEric Joyner 			      I40E_IEEE_ETS_MAXTC_SHIFT);
90*ceebc2f3SEric Joyner 
91*ceebc2f3SEric Joyner 	/* Move offset to Priority Assignment Table */
92*ceebc2f3SEric Joyner 	offset++;
93*ceebc2f3SEric Joyner 
94*ceebc2f3SEric Joyner 	/* Priority Assignment Table (4 octets)
95*ceebc2f3SEric Joyner 	 * Octets:|    1    |    2    |    3    |    4    |
96*ceebc2f3SEric Joyner 	 *        -----------------------------------------
97*ceebc2f3SEric Joyner 	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
98*ceebc2f3SEric Joyner 	 *        -----------------------------------------
99*ceebc2f3SEric Joyner 	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
100*ceebc2f3SEric Joyner 	 *        -----------------------------------------
101*ceebc2f3SEric Joyner 	 */
102*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
103*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
104*ceebc2f3SEric Joyner 				I40E_IEEE_ETS_PRIO_1_SHIFT);
105*ceebc2f3SEric Joyner 		etscfg->prioritytable[i * 2] =  priority;
106*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
107*ceebc2f3SEric Joyner 				I40E_IEEE_ETS_PRIO_0_SHIFT);
108*ceebc2f3SEric Joyner 		etscfg->prioritytable[i * 2 + 1] = priority;
109*ceebc2f3SEric Joyner 		offset++;
110*ceebc2f3SEric Joyner 	}
111*ceebc2f3SEric Joyner 
112*ceebc2f3SEric Joyner 	/* TC Bandwidth Table (8 octets)
113*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
114*ceebc2f3SEric Joyner 	 *        ---------------------------------
115*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
116*ceebc2f3SEric Joyner 	 *        ---------------------------------
117*ceebc2f3SEric Joyner 	 */
118*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
119*ceebc2f3SEric Joyner 		etscfg->tcbwtable[i] = buf[offset++];
120*ceebc2f3SEric Joyner 
121*ceebc2f3SEric Joyner 	/* TSA Assignment Table (8 octets)
122*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
123*ceebc2f3SEric Joyner 	 *        ---------------------------------
124*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
125*ceebc2f3SEric Joyner 	 *        ---------------------------------
126*ceebc2f3SEric Joyner 	 */
127*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
128*ceebc2f3SEric Joyner 		etscfg->tsatable[i] = buf[offset++];
129*ceebc2f3SEric Joyner }
130*ceebc2f3SEric Joyner 
131*ceebc2f3SEric Joyner /**
132*ceebc2f3SEric Joyner  * i40e_parse_ieee_etsrec_tlv
133*ceebc2f3SEric Joyner  * @tlv: IEEE 802.1Qaz ETS REC TLV
134*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update ETS REC data
135*ceebc2f3SEric Joyner  *
136*ceebc2f3SEric Joyner  * Parses IEEE 802.1Qaz ETS REC TLV
137*ceebc2f3SEric Joyner  **/
138*ceebc2f3SEric Joyner static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
139*ceebc2f3SEric Joyner 				       struct i40e_dcbx_config *dcbcfg)
140*ceebc2f3SEric Joyner {
141*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
142*ceebc2f3SEric Joyner 	u16 offset = 0;
143*ceebc2f3SEric Joyner 	u8 priority;
144*ceebc2f3SEric Joyner 	int i;
145*ceebc2f3SEric Joyner 
146*ceebc2f3SEric Joyner 	/* Move offset to priority table */
147*ceebc2f3SEric Joyner 	offset++;
148*ceebc2f3SEric Joyner 
149*ceebc2f3SEric Joyner 	/* Priority Assignment Table (4 octets)
150*ceebc2f3SEric Joyner 	 * Octets:|    1    |    2    |    3    |    4    |
151*ceebc2f3SEric Joyner 	 *        -----------------------------------------
152*ceebc2f3SEric Joyner 	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
153*ceebc2f3SEric Joyner 	 *        -----------------------------------------
154*ceebc2f3SEric Joyner 	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
155*ceebc2f3SEric Joyner 	 *        -----------------------------------------
156*ceebc2f3SEric Joyner 	 */
157*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
158*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
159*ceebc2f3SEric Joyner 				I40E_IEEE_ETS_PRIO_1_SHIFT);
160*ceebc2f3SEric Joyner 		dcbcfg->etsrec.prioritytable[i*2] =  priority;
161*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
162*ceebc2f3SEric Joyner 				I40E_IEEE_ETS_PRIO_0_SHIFT);
163*ceebc2f3SEric Joyner 		dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
164*ceebc2f3SEric Joyner 		offset++;
165*ceebc2f3SEric Joyner 	}
166*ceebc2f3SEric Joyner 
167*ceebc2f3SEric Joyner 	/* TC Bandwidth Table (8 octets)
168*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
169*ceebc2f3SEric Joyner 	 *        ---------------------------------
170*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
171*ceebc2f3SEric Joyner 	 *        ---------------------------------
172*ceebc2f3SEric Joyner 	 */
173*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
174*ceebc2f3SEric Joyner 		dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
175*ceebc2f3SEric Joyner 
176*ceebc2f3SEric Joyner 	/* TSA Assignment Table (8 octets)
177*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
178*ceebc2f3SEric Joyner 	 *        ---------------------------------
179*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
180*ceebc2f3SEric Joyner 	 *        ---------------------------------
181*ceebc2f3SEric Joyner 	 */
182*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
183*ceebc2f3SEric Joyner 		dcbcfg->etsrec.tsatable[i] = buf[offset++];
184*ceebc2f3SEric Joyner }
185*ceebc2f3SEric Joyner 
186*ceebc2f3SEric Joyner /**
187*ceebc2f3SEric Joyner  * i40e_parse_ieee_pfccfg_tlv
188*ceebc2f3SEric Joyner  * @tlv: IEEE 802.1Qaz PFC CFG TLV
189*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update PFC CFG data
190*ceebc2f3SEric Joyner  *
191*ceebc2f3SEric Joyner  * Parses IEEE 802.1Qaz PFC CFG TLV
192*ceebc2f3SEric Joyner  **/
193*ceebc2f3SEric Joyner static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
194*ceebc2f3SEric Joyner 				       struct i40e_dcbx_config *dcbcfg)
195*ceebc2f3SEric Joyner {
196*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
197*ceebc2f3SEric Joyner 
198*ceebc2f3SEric Joyner 	/* ----------------------------------------
199*ceebc2f3SEric Joyner 	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
200*ceebc2f3SEric Joyner 	 * |ing  |     |served| cap |              |
201*ceebc2f3SEric Joyner 	 * -----------------------------------------
202*ceebc2f3SEric Joyner 	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
203*ceebc2f3SEric Joyner 	 */
204*ceebc2f3SEric Joyner 	dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
205*ceebc2f3SEric Joyner 				   I40E_IEEE_PFC_WILLING_SHIFT);
206*ceebc2f3SEric Joyner 	dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
207*ceebc2f3SEric Joyner 			       I40E_IEEE_PFC_MBC_SHIFT);
208*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
209*ceebc2f3SEric Joyner 				  I40E_IEEE_PFC_CAP_SHIFT);
210*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfcenable = buf[1];
211*ceebc2f3SEric Joyner }
212*ceebc2f3SEric Joyner 
213*ceebc2f3SEric Joyner /**
214*ceebc2f3SEric Joyner  * i40e_parse_ieee_app_tlv
215*ceebc2f3SEric Joyner  * @tlv: IEEE 802.1Qaz APP TLV
216*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update APP PRIO data
217*ceebc2f3SEric Joyner  *
218*ceebc2f3SEric Joyner  * Parses IEEE 802.1Qaz APP PRIO TLV
219*ceebc2f3SEric Joyner  **/
220*ceebc2f3SEric Joyner static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
221*ceebc2f3SEric Joyner 				    struct i40e_dcbx_config *dcbcfg)
222*ceebc2f3SEric Joyner {
223*ceebc2f3SEric Joyner 	u16 typelength;
224*ceebc2f3SEric Joyner 	u16 offset = 0;
225*ceebc2f3SEric Joyner 	u16 length;
226*ceebc2f3SEric Joyner 	int i = 0;
227*ceebc2f3SEric Joyner 	u8 *buf;
228*ceebc2f3SEric Joyner 
229*ceebc2f3SEric Joyner 	typelength = I40E_NTOHS(tlv->typelength);
230*ceebc2f3SEric Joyner 	length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
231*ceebc2f3SEric Joyner 		       I40E_LLDP_TLV_LEN_SHIFT);
232*ceebc2f3SEric Joyner 	buf = tlv->tlvinfo;
233*ceebc2f3SEric Joyner 
234*ceebc2f3SEric Joyner 	/* The App priority table starts 5 octets after TLV header */
235*ceebc2f3SEric Joyner 	length -= (sizeof(tlv->ouisubtype) + 1);
236*ceebc2f3SEric Joyner 
237*ceebc2f3SEric Joyner 	/* Move offset to App Priority Table */
238*ceebc2f3SEric Joyner 	offset++;
239*ceebc2f3SEric Joyner 
240*ceebc2f3SEric Joyner 	/* Application Priority Table (3 octets)
241*ceebc2f3SEric Joyner 	 * Octets:|         1          |    2    |    3    |
242*ceebc2f3SEric Joyner 	 *        -----------------------------------------
243*ceebc2f3SEric Joyner 	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
244*ceebc2f3SEric Joyner 	 *        -----------------------------------------
245*ceebc2f3SEric Joyner 	 *   Bits:|23    21|20 19|18 16|15                0|
246*ceebc2f3SEric Joyner 	 *        -----------------------------------------
247*ceebc2f3SEric Joyner 	 */
248*ceebc2f3SEric Joyner 	while (offset < length) {
249*ceebc2f3SEric Joyner 		dcbcfg->app[i].priority = (u8)((buf[offset] &
250*ceebc2f3SEric Joyner 						I40E_IEEE_APP_PRIO_MASK) >>
251*ceebc2f3SEric Joyner 					       I40E_IEEE_APP_PRIO_SHIFT);
252*ceebc2f3SEric Joyner 		dcbcfg->app[i].selector = (u8)((buf[offset] &
253*ceebc2f3SEric Joyner 						I40E_IEEE_APP_SEL_MASK) >>
254*ceebc2f3SEric Joyner 					       I40E_IEEE_APP_SEL_SHIFT);
255*ceebc2f3SEric Joyner 		dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
256*ceebc2f3SEric Joyner 					     buf[offset + 2];
257*ceebc2f3SEric Joyner 		/* Move to next app */
258*ceebc2f3SEric Joyner 		offset += 3;
259*ceebc2f3SEric Joyner 		i++;
260*ceebc2f3SEric Joyner 		if (i >= I40E_DCBX_MAX_APPS)
261*ceebc2f3SEric Joyner 			break;
262*ceebc2f3SEric Joyner 	}
263*ceebc2f3SEric Joyner 
264*ceebc2f3SEric Joyner 	dcbcfg->numapps = i;
265*ceebc2f3SEric Joyner }
266*ceebc2f3SEric Joyner 
267*ceebc2f3SEric Joyner /**
268*ceebc2f3SEric Joyner  * i40e_parse_ieee_etsrec_tlv
269*ceebc2f3SEric Joyner  * @tlv: IEEE 802.1Qaz TLV
270*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update ETS REC data
271*ceebc2f3SEric Joyner  *
272*ceebc2f3SEric Joyner  * Get the TLV subtype and send it to parsing function
273*ceebc2f3SEric Joyner  * based on the subtype value
274*ceebc2f3SEric Joyner  **/
275*ceebc2f3SEric Joyner static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
276*ceebc2f3SEric Joyner 				struct i40e_dcbx_config *dcbcfg)
277*ceebc2f3SEric Joyner {
278*ceebc2f3SEric Joyner 	u32 ouisubtype;
279*ceebc2f3SEric Joyner 	u8 subtype;
280*ceebc2f3SEric Joyner 
281*ceebc2f3SEric Joyner 	ouisubtype = I40E_NTOHL(tlv->ouisubtype);
282*ceebc2f3SEric Joyner 	subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
283*ceebc2f3SEric Joyner 		       I40E_LLDP_TLV_SUBTYPE_SHIFT);
284*ceebc2f3SEric Joyner 	switch (subtype) {
285*ceebc2f3SEric Joyner 	case I40E_IEEE_SUBTYPE_ETS_CFG:
286*ceebc2f3SEric Joyner 		i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
287*ceebc2f3SEric Joyner 		break;
288*ceebc2f3SEric Joyner 	case I40E_IEEE_SUBTYPE_ETS_REC:
289*ceebc2f3SEric Joyner 		i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
290*ceebc2f3SEric Joyner 		break;
291*ceebc2f3SEric Joyner 	case I40E_IEEE_SUBTYPE_PFC_CFG:
292*ceebc2f3SEric Joyner 		i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
293*ceebc2f3SEric Joyner 		break;
294*ceebc2f3SEric Joyner 	case I40E_IEEE_SUBTYPE_APP_PRI:
295*ceebc2f3SEric Joyner 		i40e_parse_ieee_app_tlv(tlv, dcbcfg);
296*ceebc2f3SEric Joyner 		break;
297*ceebc2f3SEric Joyner 	default:
298*ceebc2f3SEric Joyner 		break;
299*ceebc2f3SEric Joyner 	}
300*ceebc2f3SEric Joyner }
301*ceebc2f3SEric Joyner 
302*ceebc2f3SEric Joyner /**
303*ceebc2f3SEric Joyner  * i40e_parse_cee_pgcfg_tlv
304*ceebc2f3SEric Joyner  * @tlv: CEE DCBX PG CFG TLV
305*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update ETS CFG data
306*ceebc2f3SEric Joyner  *
307*ceebc2f3SEric Joyner  * Parses CEE DCBX PG CFG TLV
308*ceebc2f3SEric Joyner  **/
309*ceebc2f3SEric Joyner static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
310*ceebc2f3SEric Joyner 				     struct i40e_dcbx_config *dcbcfg)
311*ceebc2f3SEric Joyner {
312*ceebc2f3SEric Joyner 	struct i40e_dcb_ets_config *etscfg;
313*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
314*ceebc2f3SEric Joyner 	u16 offset = 0;
315*ceebc2f3SEric Joyner 	u8 priority;
316*ceebc2f3SEric Joyner 	int i;
317*ceebc2f3SEric Joyner 
318*ceebc2f3SEric Joyner 	etscfg = &dcbcfg->etscfg;
319*ceebc2f3SEric Joyner 
320*ceebc2f3SEric Joyner 	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
321*ceebc2f3SEric Joyner 		etscfg->willing = 1;
322*ceebc2f3SEric Joyner 
323*ceebc2f3SEric Joyner 	etscfg->cbs = 0;
324*ceebc2f3SEric Joyner 	/* Priority Group Table (4 octets)
325*ceebc2f3SEric Joyner 	 * Octets:|    1    |    2    |    3    |    4    |
326*ceebc2f3SEric Joyner 	 *        -----------------------------------------
327*ceebc2f3SEric Joyner 	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
328*ceebc2f3SEric Joyner 	 *        -----------------------------------------
329*ceebc2f3SEric Joyner 	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
330*ceebc2f3SEric Joyner 	 *        -----------------------------------------
331*ceebc2f3SEric Joyner 	 */
332*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
333*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
334*ceebc2f3SEric Joyner 				 I40E_CEE_PGID_PRIO_1_SHIFT);
335*ceebc2f3SEric Joyner 		etscfg->prioritytable[i * 2] =  priority;
336*ceebc2f3SEric Joyner 		priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
337*ceebc2f3SEric Joyner 				 I40E_CEE_PGID_PRIO_0_SHIFT);
338*ceebc2f3SEric Joyner 		etscfg->prioritytable[i * 2 + 1] = priority;
339*ceebc2f3SEric Joyner 		offset++;
340*ceebc2f3SEric Joyner 	}
341*ceebc2f3SEric Joyner 
342*ceebc2f3SEric Joyner 	/* PG Percentage Table (8 octets)
343*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
344*ceebc2f3SEric Joyner 	 *        ---------------------------------
345*ceebc2f3SEric Joyner 	 *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
346*ceebc2f3SEric Joyner 	 *        ---------------------------------
347*ceebc2f3SEric Joyner 	 */
348*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
349*ceebc2f3SEric Joyner 		etscfg->tcbwtable[i] = buf[offset++];
350*ceebc2f3SEric Joyner 
351*ceebc2f3SEric Joyner 	/* Number of TCs supported (1 octet) */
352*ceebc2f3SEric Joyner 	etscfg->maxtcs = buf[offset];
353*ceebc2f3SEric Joyner }
354*ceebc2f3SEric Joyner 
355*ceebc2f3SEric Joyner /**
356*ceebc2f3SEric Joyner  * i40e_parse_cee_pfccfg_tlv
357*ceebc2f3SEric Joyner  * @tlv: CEE DCBX PFC CFG TLV
358*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update PFC CFG data
359*ceebc2f3SEric Joyner  *
360*ceebc2f3SEric Joyner  * Parses CEE DCBX PFC CFG TLV
361*ceebc2f3SEric Joyner  **/
362*ceebc2f3SEric Joyner static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
363*ceebc2f3SEric Joyner 				      struct i40e_dcbx_config *dcbcfg)
364*ceebc2f3SEric Joyner {
365*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
366*ceebc2f3SEric Joyner 
367*ceebc2f3SEric Joyner 	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
368*ceebc2f3SEric Joyner 		dcbcfg->pfc.willing = 1;
369*ceebc2f3SEric Joyner 
370*ceebc2f3SEric Joyner 	/* ------------------------
371*ceebc2f3SEric Joyner 	 * | PFC Enable | PFC TCs |
372*ceebc2f3SEric Joyner 	 * ------------------------
373*ceebc2f3SEric Joyner 	 * | 1 octet    | 1 octet |
374*ceebc2f3SEric Joyner 	 */
375*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfcenable = buf[0];
376*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfccap = buf[1];
377*ceebc2f3SEric Joyner }
378*ceebc2f3SEric Joyner 
379*ceebc2f3SEric Joyner /**
380*ceebc2f3SEric Joyner  * i40e_parse_cee_app_tlv
381*ceebc2f3SEric Joyner  * @tlv: CEE DCBX APP TLV
382*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update APP PRIO data
383*ceebc2f3SEric Joyner  *
384*ceebc2f3SEric Joyner  * Parses CEE DCBX APP PRIO TLV
385*ceebc2f3SEric Joyner  **/
386*ceebc2f3SEric Joyner static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
387*ceebc2f3SEric Joyner 				   struct i40e_dcbx_config *dcbcfg)
388*ceebc2f3SEric Joyner {
389*ceebc2f3SEric Joyner 	u16 length, typelength, offset = 0;
390*ceebc2f3SEric Joyner 	struct i40e_cee_app_prio *app;
391*ceebc2f3SEric Joyner 	u8 i;
392*ceebc2f3SEric Joyner 
393*ceebc2f3SEric Joyner 	typelength = I40E_NTOHS(tlv->hdr.typelen);
394*ceebc2f3SEric Joyner 	length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
395*ceebc2f3SEric Joyner 		       I40E_LLDP_TLV_LEN_SHIFT);
396*ceebc2f3SEric Joyner 
397*ceebc2f3SEric Joyner 	dcbcfg->numapps = length / sizeof(*app);
398*ceebc2f3SEric Joyner 	if (!dcbcfg->numapps)
399*ceebc2f3SEric Joyner 		return;
400*ceebc2f3SEric Joyner 	if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
401*ceebc2f3SEric Joyner 		dcbcfg->numapps = I40E_DCBX_MAX_APPS;
402*ceebc2f3SEric Joyner 
403*ceebc2f3SEric Joyner 	for (i = 0; i < dcbcfg->numapps; i++) {
404*ceebc2f3SEric Joyner 		u8 up, selector;
405*ceebc2f3SEric Joyner 
406*ceebc2f3SEric Joyner 		app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
407*ceebc2f3SEric Joyner 		for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
408*ceebc2f3SEric Joyner 			if (app->prio_map & BIT(up))
409*ceebc2f3SEric Joyner 				break;
410*ceebc2f3SEric Joyner 		}
411*ceebc2f3SEric Joyner 		dcbcfg->app[i].priority = up;
412*ceebc2f3SEric Joyner 
413*ceebc2f3SEric Joyner 		/* Get Selector from lower 2 bits, and convert to IEEE */
414*ceebc2f3SEric Joyner 		selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
415*ceebc2f3SEric Joyner 		switch (selector) {
416*ceebc2f3SEric Joyner 		case I40E_CEE_APP_SEL_ETHTYPE:
417*ceebc2f3SEric Joyner 			dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
418*ceebc2f3SEric Joyner 			break;
419*ceebc2f3SEric Joyner 		case I40E_CEE_APP_SEL_TCPIP:
420*ceebc2f3SEric Joyner 			dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
421*ceebc2f3SEric Joyner 			break;
422*ceebc2f3SEric Joyner 		default:
423*ceebc2f3SEric Joyner 			/* Keep selector as it is for unknown types */
424*ceebc2f3SEric Joyner 			dcbcfg->app[i].selector = selector;
425*ceebc2f3SEric Joyner 		}
426*ceebc2f3SEric Joyner 
427*ceebc2f3SEric Joyner 		dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol);
428*ceebc2f3SEric Joyner 		/* Move to next app */
429*ceebc2f3SEric Joyner 		offset += sizeof(*app);
430*ceebc2f3SEric Joyner 	}
431*ceebc2f3SEric Joyner }
432*ceebc2f3SEric Joyner 
433*ceebc2f3SEric Joyner /**
434*ceebc2f3SEric Joyner  * i40e_parse_cee_tlv
435*ceebc2f3SEric Joyner  * @tlv: CEE DCBX TLV
436*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update DCBX config data
437*ceebc2f3SEric Joyner  *
438*ceebc2f3SEric Joyner  * Get the TLV subtype and send it to parsing function
439*ceebc2f3SEric Joyner  * based on the subtype value
440*ceebc2f3SEric Joyner  **/
441*ceebc2f3SEric Joyner static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
442*ceebc2f3SEric Joyner 			       struct i40e_dcbx_config *dcbcfg)
443*ceebc2f3SEric Joyner {
444*ceebc2f3SEric Joyner 	u16 len, tlvlen, sublen, typelength;
445*ceebc2f3SEric Joyner 	struct i40e_cee_feat_tlv *sub_tlv;
446*ceebc2f3SEric Joyner 	u8 subtype, feat_tlv_count = 0;
447*ceebc2f3SEric Joyner 	u32 ouisubtype;
448*ceebc2f3SEric Joyner 
449*ceebc2f3SEric Joyner 	ouisubtype = I40E_NTOHL(tlv->ouisubtype);
450*ceebc2f3SEric Joyner 	subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
451*ceebc2f3SEric Joyner 		       I40E_LLDP_TLV_SUBTYPE_SHIFT);
452*ceebc2f3SEric Joyner 	/* Return if not CEE DCBX */
453*ceebc2f3SEric Joyner 	if (subtype != I40E_CEE_DCBX_TYPE)
454*ceebc2f3SEric Joyner 		return;
455*ceebc2f3SEric Joyner 
456*ceebc2f3SEric Joyner 	typelength = I40E_NTOHS(tlv->typelength);
457*ceebc2f3SEric Joyner 	tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
458*ceebc2f3SEric Joyner 			I40E_LLDP_TLV_LEN_SHIFT);
459*ceebc2f3SEric Joyner 	len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
460*ceebc2f3SEric Joyner 	      sizeof(struct i40e_cee_ctrl_tlv);
461*ceebc2f3SEric Joyner 	/* Return if no CEE DCBX Feature TLVs */
462*ceebc2f3SEric Joyner 	if (tlvlen <= len)
463*ceebc2f3SEric Joyner 		return;
464*ceebc2f3SEric Joyner 
465*ceebc2f3SEric Joyner 	sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
466*ceebc2f3SEric Joyner 	while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
467*ceebc2f3SEric Joyner 		typelength = I40E_NTOHS(sub_tlv->hdr.typelen);
468*ceebc2f3SEric Joyner 		sublen = (u16)((typelength &
469*ceebc2f3SEric Joyner 				I40E_LLDP_TLV_LEN_MASK) >>
470*ceebc2f3SEric Joyner 				I40E_LLDP_TLV_LEN_SHIFT);
471*ceebc2f3SEric Joyner 		subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
472*ceebc2f3SEric Joyner 				I40E_LLDP_TLV_TYPE_SHIFT);
473*ceebc2f3SEric Joyner 		switch (subtype) {
474*ceebc2f3SEric Joyner 		case I40E_CEE_SUBTYPE_PG_CFG:
475*ceebc2f3SEric Joyner 			i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
476*ceebc2f3SEric Joyner 			break;
477*ceebc2f3SEric Joyner 		case I40E_CEE_SUBTYPE_PFC_CFG:
478*ceebc2f3SEric Joyner 			i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
479*ceebc2f3SEric Joyner 			break;
480*ceebc2f3SEric Joyner 		case I40E_CEE_SUBTYPE_APP_PRI:
481*ceebc2f3SEric Joyner 			i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
482*ceebc2f3SEric Joyner 			break;
483*ceebc2f3SEric Joyner 		default:
484*ceebc2f3SEric Joyner 			return; /* Invalid Sub-type return */
485*ceebc2f3SEric Joyner 		}
486*ceebc2f3SEric Joyner 		feat_tlv_count++;
487*ceebc2f3SEric Joyner 		/* Move to next sub TLV */
488*ceebc2f3SEric Joyner 		sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
489*ceebc2f3SEric Joyner 						sizeof(sub_tlv->hdr.typelen) +
490*ceebc2f3SEric Joyner 						sublen);
491*ceebc2f3SEric Joyner 	}
492*ceebc2f3SEric Joyner }
493*ceebc2f3SEric Joyner 
494*ceebc2f3SEric Joyner /**
495*ceebc2f3SEric Joyner  * i40e_parse_org_tlv
496*ceebc2f3SEric Joyner  * @tlv: Organization specific TLV
497*ceebc2f3SEric Joyner  * @dcbcfg: Local store to update ETS REC data
498*ceebc2f3SEric Joyner  *
499*ceebc2f3SEric Joyner  * Currently only IEEE 802.1Qaz TLV is supported, all others
500*ceebc2f3SEric Joyner  * will be returned
501*ceebc2f3SEric Joyner  **/
502*ceebc2f3SEric Joyner static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
503*ceebc2f3SEric Joyner 			       struct i40e_dcbx_config *dcbcfg)
504*ceebc2f3SEric Joyner {
505*ceebc2f3SEric Joyner 	u32 ouisubtype;
506*ceebc2f3SEric Joyner 	u32 oui;
507*ceebc2f3SEric Joyner 
508*ceebc2f3SEric Joyner 	ouisubtype = I40E_NTOHL(tlv->ouisubtype);
509*ceebc2f3SEric Joyner 	oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
510*ceebc2f3SEric Joyner 		    I40E_LLDP_TLV_OUI_SHIFT);
511*ceebc2f3SEric Joyner 	switch (oui) {
512*ceebc2f3SEric Joyner 	case I40E_IEEE_8021QAZ_OUI:
513*ceebc2f3SEric Joyner 		i40e_parse_ieee_tlv(tlv, dcbcfg);
514*ceebc2f3SEric Joyner 		break;
515*ceebc2f3SEric Joyner 	case I40E_CEE_DCBX_OUI:
516*ceebc2f3SEric Joyner 		i40e_parse_cee_tlv(tlv, dcbcfg);
517*ceebc2f3SEric Joyner 		break;
518*ceebc2f3SEric Joyner 	default:
519*ceebc2f3SEric Joyner 		break;
520*ceebc2f3SEric Joyner 	}
521*ceebc2f3SEric Joyner }
522*ceebc2f3SEric Joyner 
523*ceebc2f3SEric Joyner /**
524*ceebc2f3SEric Joyner  * i40e_lldp_to_dcb_config
525*ceebc2f3SEric Joyner  * @lldpmib: LLDPDU to be parsed
526*ceebc2f3SEric Joyner  * @dcbcfg: store for LLDPDU data
527*ceebc2f3SEric Joyner  *
528*ceebc2f3SEric Joyner  * Parse DCB configuration from the LLDPDU
529*ceebc2f3SEric Joyner  **/
530*ceebc2f3SEric Joyner enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
531*ceebc2f3SEric Joyner 				    struct i40e_dcbx_config *dcbcfg)
532*ceebc2f3SEric Joyner {
533*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
534*ceebc2f3SEric Joyner 	struct i40e_lldp_org_tlv *tlv;
535*ceebc2f3SEric Joyner 	u16 type;
536*ceebc2f3SEric Joyner 	u16 length;
537*ceebc2f3SEric Joyner 	u16 typelength;
538*ceebc2f3SEric Joyner 	u16 offset = 0;
539*ceebc2f3SEric Joyner 
540*ceebc2f3SEric Joyner 	if (!lldpmib || !dcbcfg)
541*ceebc2f3SEric Joyner 		return I40E_ERR_PARAM;
542*ceebc2f3SEric Joyner 
543*ceebc2f3SEric Joyner 	/* set to the start of LLDPDU */
544*ceebc2f3SEric Joyner 	lldpmib += I40E_LLDP_MIB_HLEN;
545*ceebc2f3SEric Joyner 	tlv = (struct i40e_lldp_org_tlv *)lldpmib;
546*ceebc2f3SEric Joyner 	while (1) {
547*ceebc2f3SEric Joyner 		typelength = I40E_NTOHS(tlv->typelength);
548*ceebc2f3SEric Joyner 		type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
549*ceebc2f3SEric Joyner 			     I40E_LLDP_TLV_TYPE_SHIFT);
550*ceebc2f3SEric Joyner 		length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
551*ceebc2f3SEric Joyner 			       I40E_LLDP_TLV_LEN_SHIFT);
552*ceebc2f3SEric Joyner 		offset += sizeof(typelength) + length;
553*ceebc2f3SEric Joyner 
554*ceebc2f3SEric Joyner 		/* END TLV or beyond LLDPDU size */
555*ceebc2f3SEric Joyner 		if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
556*ceebc2f3SEric Joyner 			break;
557*ceebc2f3SEric Joyner 
558*ceebc2f3SEric Joyner 		switch (type) {
559*ceebc2f3SEric Joyner 		case I40E_TLV_TYPE_ORG:
560*ceebc2f3SEric Joyner 			i40e_parse_org_tlv(tlv, dcbcfg);
561*ceebc2f3SEric Joyner 			break;
562*ceebc2f3SEric Joyner 		default:
563*ceebc2f3SEric Joyner 			break;
564*ceebc2f3SEric Joyner 		}
565*ceebc2f3SEric Joyner 
566*ceebc2f3SEric Joyner 		/* Move to next TLV */
567*ceebc2f3SEric Joyner 		tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
568*ceebc2f3SEric Joyner 						    sizeof(tlv->typelength) +
569*ceebc2f3SEric Joyner 						    length);
570*ceebc2f3SEric Joyner 	}
571*ceebc2f3SEric Joyner 
572*ceebc2f3SEric Joyner 	return ret;
573*ceebc2f3SEric Joyner }
574*ceebc2f3SEric Joyner 
575*ceebc2f3SEric Joyner /**
576*ceebc2f3SEric Joyner  * i40e_aq_get_dcb_config
577*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
578*ceebc2f3SEric Joyner  * @mib_type: mib type for the query
579*ceebc2f3SEric Joyner  * @bridgetype: bridge type for the query (remote)
580*ceebc2f3SEric Joyner  * @dcbcfg: store for LLDPDU data
581*ceebc2f3SEric Joyner  *
582*ceebc2f3SEric Joyner  * Query DCB configuration from the Firmware
583*ceebc2f3SEric Joyner  **/
584*ceebc2f3SEric Joyner enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
585*ceebc2f3SEric Joyner 				   u8 bridgetype,
586*ceebc2f3SEric Joyner 				   struct i40e_dcbx_config *dcbcfg)
587*ceebc2f3SEric Joyner {
588*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
589*ceebc2f3SEric Joyner 	struct i40e_virt_mem mem;
590*ceebc2f3SEric Joyner 	u8 *lldpmib;
591*ceebc2f3SEric Joyner 
592*ceebc2f3SEric Joyner 	/* Allocate the LLDPDU */
593*ceebc2f3SEric Joyner 	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
594*ceebc2f3SEric Joyner 	if (ret)
595*ceebc2f3SEric Joyner 		return ret;
596*ceebc2f3SEric Joyner 
597*ceebc2f3SEric Joyner 	lldpmib = (u8 *)mem.va;
598*ceebc2f3SEric Joyner 	ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
599*ceebc2f3SEric Joyner 				   (void *)lldpmib, I40E_LLDPDU_SIZE,
600*ceebc2f3SEric Joyner 				   NULL, NULL, NULL);
601*ceebc2f3SEric Joyner 	if (ret)
602*ceebc2f3SEric Joyner 		goto free_mem;
603*ceebc2f3SEric Joyner 
604*ceebc2f3SEric Joyner 	/* Parse LLDP MIB to get dcb configuration */
605*ceebc2f3SEric Joyner 	ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
606*ceebc2f3SEric Joyner 
607*ceebc2f3SEric Joyner free_mem:
608*ceebc2f3SEric Joyner 	i40e_free_virt_mem(hw, &mem);
609*ceebc2f3SEric Joyner 	return ret;
610*ceebc2f3SEric Joyner }
611*ceebc2f3SEric Joyner 
612*ceebc2f3SEric Joyner /**
613*ceebc2f3SEric Joyner  * i40e_cee_to_dcb_v1_config
614*ceebc2f3SEric Joyner  * @cee_cfg: pointer to CEE v1 response configuration struct
615*ceebc2f3SEric Joyner  * @dcbcfg: DCB configuration struct
616*ceebc2f3SEric Joyner  *
617*ceebc2f3SEric Joyner  * Convert CEE v1 configuration from firmware to DCB configuration
618*ceebc2f3SEric Joyner  **/
619*ceebc2f3SEric Joyner static void i40e_cee_to_dcb_v1_config(
620*ceebc2f3SEric Joyner 			struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
621*ceebc2f3SEric Joyner 			struct i40e_dcbx_config *dcbcfg)
622*ceebc2f3SEric Joyner {
623*ceebc2f3SEric Joyner 	u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
624*ceebc2f3SEric Joyner 	u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
625*ceebc2f3SEric Joyner 	u8 i, tc, err;
626*ceebc2f3SEric Joyner 
627*ceebc2f3SEric Joyner 	/* CEE PG data to ETS config */
628*ceebc2f3SEric Joyner 	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
629*ceebc2f3SEric Joyner 
630*ceebc2f3SEric Joyner 	/* Note that the FW creates the oper_prio_tc nibbles reversed
631*ceebc2f3SEric Joyner 	 * from those in the CEE Priority Group sub-TLV.
632*ceebc2f3SEric Joyner 	 */
633*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
634*ceebc2f3SEric Joyner 		tc = (u8)((cee_cfg->oper_prio_tc[i] &
635*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_0_MASK) >>
636*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_0_SHIFT);
637*ceebc2f3SEric Joyner 		dcbcfg->etscfg.prioritytable[i*2] =  tc;
638*ceebc2f3SEric Joyner 		tc = (u8)((cee_cfg->oper_prio_tc[i] &
639*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_1_MASK) >>
640*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_1_SHIFT);
641*ceebc2f3SEric Joyner 		dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
642*ceebc2f3SEric Joyner 	}
643*ceebc2f3SEric Joyner 
644*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
645*ceebc2f3SEric Joyner 		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
646*ceebc2f3SEric Joyner 
647*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
648*ceebc2f3SEric Joyner 		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
649*ceebc2f3SEric Joyner 			/* Map it to next empty TC */
650*ceebc2f3SEric Joyner 			dcbcfg->etscfg.prioritytable[i] =
651*ceebc2f3SEric Joyner 						cee_cfg->oper_num_tc - 1;
652*ceebc2f3SEric Joyner 			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
653*ceebc2f3SEric Joyner 		} else {
654*ceebc2f3SEric Joyner 			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
655*ceebc2f3SEric Joyner 		}
656*ceebc2f3SEric Joyner 	}
657*ceebc2f3SEric Joyner 
658*ceebc2f3SEric Joyner 	/* CEE PFC data to ETS config */
659*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
660*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
661*ceebc2f3SEric Joyner 
662*ceebc2f3SEric Joyner 	status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
663*ceebc2f3SEric Joyner 		  I40E_AQC_CEE_APP_STATUS_SHIFT;
664*ceebc2f3SEric Joyner 	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
665*ceebc2f3SEric Joyner 	/* Add APPs if Error is False */
666*ceebc2f3SEric Joyner 	if (!err) {
667*ceebc2f3SEric Joyner 		/* CEE operating configuration supports FCoE/iSCSI/FIP only */
668*ceebc2f3SEric Joyner 		dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
669*ceebc2f3SEric Joyner 
670*ceebc2f3SEric Joyner 		/* FCoE APP */
671*ceebc2f3SEric Joyner 		dcbcfg->app[0].priority =
672*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
673*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_FCOE_SHIFT;
674*ceebc2f3SEric Joyner 		dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
675*ceebc2f3SEric Joyner 		dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
676*ceebc2f3SEric Joyner 
677*ceebc2f3SEric Joyner 		/* iSCSI APP */
678*ceebc2f3SEric Joyner 		dcbcfg->app[1].priority =
679*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
680*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_ISCSI_SHIFT;
681*ceebc2f3SEric Joyner 		dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
682*ceebc2f3SEric Joyner 		dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
683*ceebc2f3SEric Joyner 
684*ceebc2f3SEric Joyner 		/* FIP APP */
685*ceebc2f3SEric Joyner 		dcbcfg->app[2].priority =
686*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
687*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_FIP_SHIFT;
688*ceebc2f3SEric Joyner 		dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
689*ceebc2f3SEric Joyner 		dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
690*ceebc2f3SEric Joyner 	}
691*ceebc2f3SEric Joyner }
692*ceebc2f3SEric Joyner 
693*ceebc2f3SEric Joyner /**
694*ceebc2f3SEric Joyner  * i40e_cee_to_dcb_config
695*ceebc2f3SEric Joyner  * @cee_cfg: pointer to CEE configuration struct
696*ceebc2f3SEric Joyner  * @dcbcfg: DCB configuration struct
697*ceebc2f3SEric Joyner  *
698*ceebc2f3SEric Joyner  * Convert CEE configuration from firmware to DCB configuration
699*ceebc2f3SEric Joyner  **/
700*ceebc2f3SEric Joyner static void i40e_cee_to_dcb_config(
701*ceebc2f3SEric Joyner 				struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
702*ceebc2f3SEric Joyner 				struct i40e_dcbx_config *dcbcfg)
703*ceebc2f3SEric Joyner {
704*ceebc2f3SEric Joyner 	u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
705*ceebc2f3SEric Joyner 	u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
706*ceebc2f3SEric Joyner 	u8 i, tc, err, sync, oper;
707*ceebc2f3SEric Joyner 
708*ceebc2f3SEric Joyner 	/* CEE PG data to ETS config */
709*ceebc2f3SEric Joyner 	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
710*ceebc2f3SEric Joyner 
711*ceebc2f3SEric Joyner 	/* Note that the FW creates the oper_prio_tc nibbles reversed
712*ceebc2f3SEric Joyner 	 * from those in the CEE Priority Group sub-TLV.
713*ceebc2f3SEric Joyner 	 */
714*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
715*ceebc2f3SEric Joyner 		tc = (u8)((cee_cfg->oper_prio_tc[i] &
716*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_0_MASK) >>
717*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_0_SHIFT);
718*ceebc2f3SEric Joyner 		dcbcfg->etscfg.prioritytable[i*2] =  tc;
719*ceebc2f3SEric Joyner 		tc = (u8)((cee_cfg->oper_prio_tc[i] &
720*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_1_MASK) >>
721*ceebc2f3SEric Joyner 			 I40E_CEE_PGID_PRIO_1_SHIFT);
722*ceebc2f3SEric Joyner 		dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
723*ceebc2f3SEric Joyner 	}
724*ceebc2f3SEric Joyner 
725*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
726*ceebc2f3SEric Joyner 		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
727*ceebc2f3SEric Joyner 
728*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
729*ceebc2f3SEric Joyner 		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
730*ceebc2f3SEric Joyner 			/* Map it to next empty TC */
731*ceebc2f3SEric Joyner 			dcbcfg->etscfg.prioritytable[i] =
732*ceebc2f3SEric Joyner 						cee_cfg->oper_num_tc - 1;
733*ceebc2f3SEric Joyner 			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
734*ceebc2f3SEric Joyner 		} else {
735*ceebc2f3SEric Joyner 			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
736*ceebc2f3SEric Joyner 		}
737*ceebc2f3SEric Joyner 	}
738*ceebc2f3SEric Joyner 
739*ceebc2f3SEric Joyner 	/* CEE PFC data to ETS config */
740*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
741*ceebc2f3SEric Joyner 	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
742*ceebc2f3SEric Joyner 
743*ceebc2f3SEric Joyner 	i = 0;
744*ceebc2f3SEric Joyner 	status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
745*ceebc2f3SEric Joyner 		  I40E_AQC_CEE_FCOE_STATUS_SHIFT;
746*ceebc2f3SEric Joyner 	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
747*ceebc2f3SEric Joyner 	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
748*ceebc2f3SEric Joyner 	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
749*ceebc2f3SEric Joyner 	/* Add FCoE APP if Error is False and Oper/Sync is True */
750*ceebc2f3SEric Joyner 	if (!err && sync && oper) {
751*ceebc2f3SEric Joyner 		/* FCoE APP */
752*ceebc2f3SEric Joyner 		dcbcfg->app[i].priority =
753*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
754*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_FCOE_SHIFT;
755*ceebc2f3SEric Joyner 		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
756*ceebc2f3SEric Joyner 		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
757*ceebc2f3SEric Joyner 		i++;
758*ceebc2f3SEric Joyner 	}
759*ceebc2f3SEric Joyner 
760*ceebc2f3SEric Joyner 	status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
761*ceebc2f3SEric Joyner 		  I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
762*ceebc2f3SEric Joyner 	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
763*ceebc2f3SEric Joyner 	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
764*ceebc2f3SEric Joyner 	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
765*ceebc2f3SEric Joyner 	/* Add iSCSI APP if Error is False and Oper/Sync is True */
766*ceebc2f3SEric Joyner 	if (!err && sync && oper) {
767*ceebc2f3SEric Joyner 		/* iSCSI APP */
768*ceebc2f3SEric Joyner 		dcbcfg->app[i].priority =
769*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
770*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_ISCSI_SHIFT;
771*ceebc2f3SEric Joyner 		dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
772*ceebc2f3SEric Joyner 		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
773*ceebc2f3SEric Joyner 		i++;
774*ceebc2f3SEric Joyner 	}
775*ceebc2f3SEric Joyner 
776*ceebc2f3SEric Joyner 	status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
777*ceebc2f3SEric Joyner 		  I40E_AQC_CEE_FIP_STATUS_SHIFT;
778*ceebc2f3SEric Joyner 	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
779*ceebc2f3SEric Joyner 	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
780*ceebc2f3SEric Joyner 	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
781*ceebc2f3SEric Joyner 	/* Add FIP APP if Error is False and Oper/Sync is True */
782*ceebc2f3SEric Joyner 	if (!err && sync && oper) {
783*ceebc2f3SEric Joyner 		/* FIP APP */
784*ceebc2f3SEric Joyner 		dcbcfg->app[i].priority =
785*ceebc2f3SEric Joyner 			(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
786*ceebc2f3SEric Joyner 			 I40E_AQC_CEE_APP_FIP_SHIFT;
787*ceebc2f3SEric Joyner 		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
788*ceebc2f3SEric Joyner 		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
789*ceebc2f3SEric Joyner 		i++;
790*ceebc2f3SEric Joyner 	}
791*ceebc2f3SEric Joyner 	dcbcfg->numapps = i;
792*ceebc2f3SEric Joyner }
793*ceebc2f3SEric Joyner 
794*ceebc2f3SEric Joyner /**
795*ceebc2f3SEric Joyner  * i40e_get_ieee_dcb_config
796*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
797*ceebc2f3SEric Joyner  *
798*ceebc2f3SEric Joyner  * Get IEEE mode DCB configuration from the Firmware
799*ceebc2f3SEric Joyner  **/
800*ceebc2f3SEric Joyner static enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw)
801*ceebc2f3SEric Joyner {
802*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
803*ceebc2f3SEric Joyner 
804*ceebc2f3SEric Joyner 	/* IEEE mode */
805*ceebc2f3SEric Joyner 	hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
806*ceebc2f3SEric Joyner 	/* Get Local DCB Config */
807*ceebc2f3SEric Joyner 	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
808*ceebc2f3SEric Joyner 				     &hw->local_dcbx_config);
809*ceebc2f3SEric Joyner 	if (ret)
810*ceebc2f3SEric Joyner 		goto out;
811*ceebc2f3SEric Joyner 
812*ceebc2f3SEric Joyner 	/* Get Remote DCB Config */
813*ceebc2f3SEric Joyner 	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
814*ceebc2f3SEric Joyner 				     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
815*ceebc2f3SEric Joyner 				     &hw->remote_dcbx_config);
816*ceebc2f3SEric Joyner 	/* Don't treat ENOENT as an error for Remote MIBs */
817*ceebc2f3SEric Joyner 	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
818*ceebc2f3SEric Joyner 		ret = I40E_SUCCESS;
819*ceebc2f3SEric Joyner 
820*ceebc2f3SEric Joyner out:
821*ceebc2f3SEric Joyner 	return ret;
822*ceebc2f3SEric Joyner }
823*ceebc2f3SEric Joyner 
824*ceebc2f3SEric Joyner /**
825*ceebc2f3SEric Joyner  * i40e_get_dcb_config
826*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
827*ceebc2f3SEric Joyner  *
828*ceebc2f3SEric Joyner  * Get DCB configuration from the Firmware
829*ceebc2f3SEric Joyner  **/
830*ceebc2f3SEric Joyner enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
831*ceebc2f3SEric Joyner {
832*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
833*ceebc2f3SEric Joyner 	struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
834*ceebc2f3SEric Joyner 	struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
835*ceebc2f3SEric Joyner 
836*ceebc2f3SEric Joyner 	/* If Firmware version < v4.33 on X710/XL710, IEEE only */
837*ceebc2f3SEric Joyner 	if ((hw->mac.type == I40E_MAC_XL710) &&
838*ceebc2f3SEric Joyner 	    (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
839*ceebc2f3SEric Joyner 	      (hw->aq.fw_maj_ver < 4)))
840*ceebc2f3SEric Joyner 		return i40e_get_ieee_dcb_config(hw);
841*ceebc2f3SEric Joyner 
842*ceebc2f3SEric Joyner 	/* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
843*ceebc2f3SEric Joyner 	if ((hw->mac.type == I40E_MAC_XL710) &&
844*ceebc2f3SEric Joyner 	    ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
845*ceebc2f3SEric Joyner 		ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
846*ceebc2f3SEric Joyner 						 sizeof(cee_v1_cfg), NULL);
847*ceebc2f3SEric Joyner 		if (ret == I40E_SUCCESS) {
848*ceebc2f3SEric Joyner 			/* CEE mode */
849*ceebc2f3SEric Joyner 			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
850*ceebc2f3SEric Joyner 			hw->local_dcbx_config.tlv_status =
851*ceebc2f3SEric Joyner 					LE16_TO_CPU(cee_v1_cfg.tlv_status);
852*ceebc2f3SEric Joyner 			i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
853*ceebc2f3SEric Joyner 						  &hw->local_dcbx_config);
854*ceebc2f3SEric Joyner 		}
855*ceebc2f3SEric Joyner 	} else {
856*ceebc2f3SEric Joyner 		ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
857*ceebc2f3SEric Joyner 						 sizeof(cee_cfg), NULL);
858*ceebc2f3SEric Joyner 		if (ret == I40E_SUCCESS) {
859*ceebc2f3SEric Joyner 			/* CEE mode */
860*ceebc2f3SEric Joyner 			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
861*ceebc2f3SEric Joyner 			hw->local_dcbx_config.tlv_status =
862*ceebc2f3SEric Joyner 					LE32_TO_CPU(cee_cfg.tlv_status);
863*ceebc2f3SEric Joyner 			i40e_cee_to_dcb_config(&cee_cfg,
864*ceebc2f3SEric Joyner 					       &hw->local_dcbx_config);
865*ceebc2f3SEric Joyner 		}
866*ceebc2f3SEric Joyner 	}
867*ceebc2f3SEric Joyner 
868*ceebc2f3SEric Joyner 	/* CEE mode not enabled try querying IEEE data */
869*ceebc2f3SEric Joyner 	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
870*ceebc2f3SEric Joyner 		return i40e_get_ieee_dcb_config(hw);
871*ceebc2f3SEric Joyner 
872*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
873*ceebc2f3SEric Joyner 		goto out;
874*ceebc2f3SEric Joyner 
875*ceebc2f3SEric Joyner 	/* Get CEE DCB Desired Config */
876*ceebc2f3SEric Joyner 	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
877*ceebc2f3SEric Joyner 				     &hw->desired_dcbx_config);
878*ceebc2f3SEric Joyner 	if (ret)
879*ceebc2f3SEric Joyner 		goto out;
880*ceebc2f3SEric Joyner 
881*ceebc2f3SEric Joyner 	/* Get Remote DCB Config */
882*ceebc2f3SEric Joyner 	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
883*ceebc2f3SEric Joyner 			     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
884*ceebc2f3SEric Joyner 			     &hw->remote_dcbx_config);
885*ceebc2f3SEric Joyner 	/* Don't treat ENOENT as an error for Remote MIBs */
886*ceebc2f3SEric Joyner 	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
887*ceebc2f3SEric Joyner 		ret = I40E_SUCCESS;
888*ceebc2f3SEric Joyner 
889*ceebc2f3SEric Joyner out:
890*ceebc2f3SEric Joyner 	return ret;
891*ceebc2f3SEric Joyner }
892*ceebc2f3SEric Joyner 
893*ceebc2f3SEric Joyner /**
894*ceebc2f3SEric Joyner  * i40e_init_dcb
895*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
896*ceebc2f3SEric Joyner  *
897*ceebc2f3SEric Joyner  * Update DCB configuration from the Firmware
898*ceebc2f3SEric Joyner  **/
899*ceebc2f3SEric Joyner enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw)
900*ceebc2f3SEric Joyner {
901*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
902*ceebc2f3SEric Joyner 	struct i40e_lldp_variables lldp_cfg;
903*ceebc2f3SEric Joyner 	u8 adminstatus = 0;
904*ceebc2f3SEric Joyner 
905*ceebc2f3SEric Joyner 	if (!hw->func_caps.dcb)
906*ceebc2f3SEric Joyner 		return ret;
907*ceebc2f3SEric Joyner 
908*ceebc2f3SEric Joyner 	/* Read LLDP NVM area */
909*ceebc2f3SEric Joyner 	ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
910*ceebc2f3SEric Joyner 	if (ret)
911*ceebc2f3SEric Joyner 		return ret;
912*ceebc2f3SEric Joyner 
913*ceebc2f3SEric Joyner 	/* Get the LLDP AdminStatus for the current port */
914*ceebc2f3SEric Joyner 	adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
915*ceebc2f3SEric Joyner 	adminstatus &= 0xF;
916*ceebc2f3SEric Joyner 
917*ceebc2f3SEric Joyner 	/* LLDP agent disabled */
918*ceebc2f3SEric Joyner 	if (!adminstatus) {
919*ceebc2f3SEric Joyner 		hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
920*ceebc2f3SEric Joyner 		return ret;
921*ceebc2f3SEric Joyner 	}
922*ceebc2f3SEric Joyner 
923*ceebc2f3SEric Joyner 	/* Get DCBX status */
924*ceebc2f3SEric Joyner 	ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
925*ceebc2f3SEric Joyner 	if (ret)
926*ceebc2f3SEric Joyner 		return ret;
927*ceebc2f3SEric Joyner 
928*ceebc2f3SEric Joyner 	/* Check the DCBX Status */
929*ceebc2f3SEric Joyner 	switch (hw->dcbx_status) {
930*ceebc2f3SEric Joyner 	case I40E_DCBX_STATUS_DONE:
931*ceebc2f3SEric Joyner 	case I40E_DCBX_STATUS_IN_PROGRESS:
932*ceebc2f3SEric Joyner 		/* Get current DCBX configuration */
933*ceebc2f3SEric Joyner 		ret = i40e_get_dcb_config(hw);
934*ceebc2f3SEric Joyner 		if (ret)
935*ceebc2f3SEric Joyner 			return ret;
936*ceebc2f3SEric Joyner 		break;
937*ceebc2f3SEric Joyner 	case I40E_DCBX_STATUS_DISABLED:
938*ceebc2f3SEric Joyner 		return ret;
939*ceebc2f3SEric Joyner 	case I40E_DCBX_STATUS_NOT_STARTED:
940*ceebc2f3SEric Joyner 	case I40E_DCBX_STATUS_MULTIPLE_PEERS:
941*ceebc2f3SEric Joyner 	default:
942*ceebc2f3SEric Joyner 		break;
943*ceebc2f3SEric Joyner 	}
944*ceebc2f3SEric Joyner 
945*ceebc2f3SEric Joyner 	/* Configure the LLDP MIB change event */
946*ceebc2f3SEric Joyner 	ret = i40e_aq_cfg_lldp_mib_change_event(hw, TRUE, NULL);
947*ceebc2f3SEric Joyner 	if (ret)
948*ceebc2f3SEric Joyner 		return ret;
949*ceebc2f3SEric Joyner 
950*ceebc2f3SEric Joyner 	return ret;
951*ceebc2f3SEric Joyner }
952*ceebc2f3SEric Joyner 
953*ceebc2f3SEric Joyner /**
954*ceebc2f3SEric Joyner  * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
955*ceebc2f3SEric Joyner  * @tlv: Fill the ETS config data in IEEE format
956*ceebc2f3SEric Joyner  * @dcbcfg: Local store which holds the DCB Config
957*ceebc2f3SEric Joyner  *
958*ceebc2f3SEric Joyner  * Prepare IEEE 802.1Qaz ETS CFG TLV
959*ceebc2f3SEric Joyner  **/
960*ceebc2f3SEric Joyner static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
961*ceebc2f3SEric Joyner 				  struct i40e_dcbx_config *dcbcfg)
962*ceebc2f3SEric Joyner {
963*ceebc2f3SEric Joyner 	u8 priority0, priority1, maxtcwilling = 0;
964*ceebc2f3SEric Joyner 	struct i40e_dcb_ets_config *etscfg;
965*ceebc2f3SEric Joyner 	u16 offset = 0, typelength, i;
966*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
967*ceebc2f3SEric Joyner 	u32 ouisubtype;
968*ceebc2f3SEric Joyner 
969*ceebc2f3SEric Joyner 	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
970*ceebc2f3SEric Joyner 			I40E_IEEE_ETS_TLV_LENGTH);
971*ceebc2f3SEric Joyner 	tlv->typelength = I40E_HTONS(typelength);
972*ceebc2f3SEric Joyner 
973*ceebc2f3SEric Joyner 	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
974*ceebc2f3SEric Joyner 			I40E_IEEE_SUBTYPE_ETS_CFG);
975*ceebc2f3SEric Joyner 	tlv->ouisubtype = I40E_HTONL(ouisubtype);
976*ceebc2f3SEric Joyner 
977*ceebc2f3SEric Joyner 	/* First Octet post subtype
978*ceebc2f3SEric Joyner 	 * --------------------------
979*ceebc2f3SEric Joyner 	 * |will-|CBS  | Re-  | Max |
980*ceebc2f3SEric Joyner 	 * |ing  |     |served| TCs |
981*ceebc2f3SEric Joyner 	 * --------------------------
982*ceebc2f3SEric Joyner 	 * |1bit | 1bit|3 bits|3bits|
983*ceebc2f3SEric Joyner 	 */
984*ceebc2f3SEric Joyner 	etscfg = &dcbcfg->etscfg;
985*ceebc2f3SEric Joyner 	if (etscfg->willing)
986*ceebc2f3SEric Joyner 		maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
987*ceebc2f3SEric Joyner 	maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
988*ceebc2f3SEric Joyner 	buf[offset] = maxtcwilling;
989*ceebc2f3SEric Joyner 
990*ceebc2f3SEric Joyner 	/* Move offset to Priority Assignment Table */
991*ceebc2f3SEric Joyner 	offset++;
992*ceebc2f3SEric Joyner 
993*ceebc2f3SEric Joyner 	/* Priority Assignment Table (4 octets)
994*ceebc2f3SEric Joyner 	 * Octets:|    1    |    2    |    3    |    4    |
995*ceebc2f3SEric Joyner 	 *        -----------------------------------------
996*ceebc2f3SEric Joyner 	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
997*ceebc2f3SEric Joyner 	 *        -----------------------------------------
998*ceebc2f3SEric Joyner 	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
999*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1000*ceebc2f3SEric Joyner 	 */
1001*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
1002*ceebc2f3SEric Joyner 		priority0 = etscfg->prioritytable[i * 2] & 0xF;
1003*ceebc2f3SEric Joyner 		priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
1004*ceebc2f3SEric Joyner 		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1005*ceebc2f3SEric Joyner 				priority1;
1006*ceebc2f3SEric Joyner 		offset++;
1007*ceebc2f3SEric Joyner 	}
1008*ceebc2f3SEric Joyner 
1009*ceebc2f3SEric Joyner 	/* TC Bandwidth Table (8 octets)
1010*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1011*ceebc2f3SEric Joyner 	 *        ---------------------------------
1012*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1013*ceebc2f3SEric Joyner 	 *        ---------------------------------
1014*ceebc2f3SEric Joyner 	 */
1015*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1016*ceebc2f3SEric Joyner 		buf[offset++] = etscfg->tcbwtable[i];
1017*ceebc2f3SEric Joyner 
1018*ceebc2f3SEric Joyner 	/* TSA Assignment Table (8 octets)
1019*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1020*ceebc2f3SEric Joyner 	 *        ---------------------------------
1021*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1022*ceebc2f3SEric Joyner 	 *        ---------------------------------
1023*ceebc2f3SEric Joyner 	 */
1024*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1025*ceebc2f3SEric Joyner 		buf[offset++] = etscfg->tsatable[i];
1026*ceebc2f3SEric Joyner }
1027*ceebc2f3SEric Joyner 
1028*ceebc2f3SEric Joyner /**
1029*ceebc2f3SEric Joyner  * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1030*ceebc2f3SEric Joyner  * @tlv: Fill ETS Recommended TLV in IEEE format
1031*ceebc2f3SEric Joyner  * @dcbcfg: Local store which holds the DCB Config
1032*ceebc2f3SEric Joyner  *
1033*ceebc2f3SEric Joyner  * Prepare IEEE 802.1Qaz ETS REC TLV
1034*ceebc2f3SEric Joyner  **/
1035*ceebc2f3SEric Joyner static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
1036*ceebc2f3SEric Joyner 				     struct i40e_dcbx_config *dcbcfg)
1037*ceebc2f3SEric Joyner {
1038*ceebc2f3SEric Joyner 	struct i40e_dcb_ets_config *etsrec;
1039*ceebc2f3SEric Joyner 	u16 offset = 0, typelength, i;
1040*ceebc2f3SEric Joyner 	u8 priority0, priority1;
1041*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
1042*ceebc2f3SEric Joyner 	u32 ouisubtype;
1043*ceebc2f3SEric Joyner 
1044*ceebc2f3SEric Joyner 	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1045*ceebc2f3SEric Joyner 			I40E_IEEE_ETS_TLV_LENGTH);
1046*ceebc2f3SEric Joyner 	tlv->typelength = I40E_HTONS(typelength);
1047*ceebc2f3SEric Joyner 
1048*ceebc2f3SEric Joyner 	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1049*ceebc2f3SEric Joyner 			I40E_IEEE_SUBTYPE_ETS_REC);
1050*ceebc2f3SEric Joyner 	tlv->ouisubtype = I40E_HTONL(ouisubtype);
1051*ceebc2f3SEric Joyner 
1052*ceebc2f3SEric Joyner 	etsrec = &dcbcfg->etsrec;
1053*ceebc2f3SEric Joyner 	/* First Octet is reserved */
1054*ceebc2f3SEric Joyner 	/* Move offset to Priority Assignment Table */
1055*ceebc2f3SEric Joyner 	offset++;
1056*ceebc2f3SEric Joyner 
1057*ceebc2f3SEric Joyner 	/* Priority Assignment Table (4 octets)
1058*ceebc2f3SEric Joyner 	 * Octets:|    1    |    2    |    3    |    4    |
1059*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1060*ceebc2f3SEric Joyner 	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1061*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1062*ceebc2f3SEric Joyner 	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
1063*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1064*ceebc2f3SEric Joyner 	 */
1065*ceebc2f3SEric Joyner 	for (i = 0; i < 4; i++) {
1066*ceebc2f3SEric Joyner 		priority0 = etsrec->prioritytable[i * 2] & 0xF;
1067*ceebc2f3SEric Joyner 		priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
1068*ceebc2f3SEric Joyner 		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1069*ceebc2f3SEric Joyner 				priority1;
1070*ceebc2f3SEric Joyner 		offset++;
1071*ceebc2f3SEric Joyner 	}
1072*ceebc2f3SEric Joyner 
1073*ceebc2f3SEric Joyner 	/* TC Bandwidth Table (8 octets)
1074*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1075*ceebc2f3SEric Joyner 	 *        ---------------------------------
1076*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1077*ceebc2f3SEric Joyner 	 *        ---------------------------------
1078*ceebc2f3SEric Joyner 	 */
1079*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1080*ceebc2f3SEric Joyner 		buf[offset++] = etsrec->tcbwtable[i];
1081*ceebc2f3SEric Joyner 
1082*ceebc2f3SEric Joyner 	/* TSA Assignment Table (8 octets)
1083*ceebc2f3SEric Joyner 	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1084*ceebc2f3SEric Joyner 	 *        ---------------------------------
1085*ceebc2f3SEric Joyner 	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1086*ceebc2f3SEric Joyner 	 *        ---------------------------------
1087*ceebc2f3SEric Joyner 	 */
1088*ceebc2f3SEric Joyner 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1089*ceebc2f3SEric Joyner 		buf[offset++] = etsrec->tsatable[i];
1090*ceebc2f3SEric Joyner }
1091*ceebc2f3SEric Joyner 
1092*ceebc2f3SEric Joyner  /**
1093*ceebc2f3SEric Joyner  * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1094*ceebc2f3SEric Joyner  * @tlv: Fill PFC TLV in IEEE format
1095*ceebc2f3SEric Joyner  * @dcbcfg: Local store to get PFC CFG data
1096*ceebc2f3SEric Joyner  *
1097*ceebc2f3SEric Joyner  * Prepare IEEE 802.1Qaz PFC CFG TLV
1098*ceebc2f3SEric Joyner  **/
1099*ceebc2f3SEric Joyner static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
1100*ceebc2f3SEric Joyner 				  struct i40e_dcbx_config *dcbcfg)
1101*ceebc2f3SEric Joyner {
1102*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
1103*ceebc2f3SEric Joyner 	u32 ouisubtype;
1104*ceebc2f3SEric Joyner 	u16 typelength;
1105*ceebc2f3SEric Joyner 
1106*ceebc2f3SEric Joyner 	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1107*ceebc2f3SEric Joyner 			I40E_IEEE_PFC_TLV_LENGTH);
1108*ceebc2f3SEric Joyner 	tlv->typelength = I40E_HTONS(typelength);
1109*ceebc2f3SEric Joyner 
1110*ceebc2f3SEric Joyner 	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1111*ceebc2f3SEric Joyner 			I40E_IEEE_SUBTYPE_PFC_CFG);
1112*ceebc2f3SEric Joyner 	tlv->ouisubtype = I40E_HTONL(ouisubtype);
1113*ceebc2f3SEric Joyner 
1114*ceebc2f3SEric Joyner 	/* ----------------------------------------
1115*ceebc2f3SEric Joyner 	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
1116*ceebc2f3SEric Joyner 	 * |ing  |     |served| cap |              |
1117*ceebc2f3SEric Joyner 	 * -----------------------------------------
1118*ceebc2f3SEric Joyner 	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
1119*ceebc2f3SEric Joyner 	 */
1120*ceebc2f3SEric Joyner 	if (dcbcfg->pfc.willing)
1121*ceebc2f3SEric Joyner 		buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
1122*ceebc2f3SEric Joyner 
1123*ceebc2f3SEric Joyner 	if (dcbcfg->pfc.mbc)
1124*ceebc2f3SEric Joyner 		buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
1125*ceebc2f3SEric Joyner 
1126*ceebc2f3SEric Joyner 	buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1127*ceebc2f3SEric Joyner 	buf[1] = dcbcfg->pfc.pfcenable;
1128*ceebc2f3SEric Joyner }
1129*ceebc2f3SEric Joyner 
1130*ceebc2f3SEric Joyner /**
1131*ceebc2f3SEric Joyner  * i40e_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format
1132*ceebc2f3SEric Joyner  * @tlv: Fill APP TLV in IEEE format
1133*ceebc2f3SEric Joyner  * @dcbcfg: Local store to get APP CFG data
1134*ceebc2f3SEric Joyner  *
1135*ceebc2f3SEric Joyner  * Prepare IEEE 802.1Qaz APP CFG TLV
1136*ceebc2f3SEric Joyner  **/
1137*ceebc2f3SEric Joyner static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
1138*ceebc2f3SEric Joyner 				      struct i40e_dcbx_config *dcbcfg)
1139*ceebc2f3SEric Joyner {
1140*ceebc2f3SEric Joyner 	u16 typelength, length, offset = 0;
1141*ceebc2f3SEric Joyner 	u8 priority, selector, i = 0;
1142*ceebc2f3SEric Joyner 	u8 *buf = tlv->tlvinfo;
1143*ceebc2f3SEric Joyner 	u32 ouisubtype;
1144*ceebc2f3SEric Joyner 
1145*ceebc2f3SEric Joyner 	/* No APP TLVs then just return */
1146*ceebc2f3SEric Joyner 	if (dcbcfg->numapps == 0)
1147*ceebc2f3SEric Joyner 		return;
1148*ceebc2f3SEric Joyner 	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1149*ceebc2f3SEric Joyner 			I40E_IEEE_SUBTYPE_APP_PRI);
1150*ceebc2f3SEric Joyner 	tlv->ouisubtype = I40E_HTONL(ouisubtype);
1151*ceebc2f3SEric Joyner 
1152*ceebc2f3SEric Joyner 	/* Move offset to App Priority Table */
1153*ceebc2f3SEric Joyner 	offset++;
1154*ceebc2f3SEric Joyner 	/* Application Priority Table (3 octets)
1155*ceebc2f3SEric Joyner 	 * Octets:|         1          |    2    |    3    |
1156*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1157*ceebc2f3SEric Joyner 	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
1158*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1159*ceebc2f3SEric Joyner 	 *   Bits:|23    21|20 19|18 16|15                0|
1160*ceebc2f3SEric Joyner 	 *        -----------------------------------------
1161*ceebc2f3SEric Joyner 	 */
1162*ceebc2f3SEric Joyner 	while (i < dcbcfg->numapps) {
1163*ceebc2f3SEric Joyner 		priority = dcbcfg->app[i].priority & 0x7;
1164*ceebc2f3SEric Joyner 		selector = dcbcfg->app[i].selector & 0x7;
1165*ceebc2f3SEric Joyner 		buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
1166*ceebc2f3SEric Joyner 		buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
1167*ceebc2f3SEric Joyner 		buf[offset + 2] =  dcbcfg->app[i].protocolid & 0xFF;
1168*ceebc2f3SEric Joyner 		/* Move to next app */
1169*ceebc2f3SEric Joyner 		offset += 3;
1170*ceebc2f3SEric Joyner 		i++;
1171*ceebc2f3SEric Joyner 		if (i >= I40E_DCBX_MAX_APPS)
1172*ceebc2f3SEric Joyner 			break;
1173*ceebc2f3SEric Joyner 	}
1174*ceebc2f3SEric Joyner 	/* length includes size of ouisubtype + 1 reserved + 3*numapps */
1175*ceebc2f3SEric Joyner 	length = sizeof(tlv->ouisubtype) + 1 + (i*3);
1176*ceebc2f3SEric Joyner 	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1177*ceebc2f3SEric Joyner 		(length & 0x1FF));
1178*ceebc2f3SEric Joyner 	tlv->typelength = I40E_HTONS(typelength);
1179*ceebc2f3SEric Joyner }
1180*ceebc2f3SEric Joyner 
1181*ceebc2f3SEric Joyner  /**
1182*ceebc2f3SEric Joyner  * i40e_add_dcb_tlv - Add all IEEE TLVs
1183*ceebc2f3SEric Joyner  * @tlv: pointer to org tlv
1184*ceebc2f3SEric Joyner  *
1185*ceebc2f3SEric Joyner  * add tlv information
1186*ceebc2f3SEric Joyner  **/
1187*ceebc2f3SEric Joyner static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
1188*ceebc2f3SEric Joyner 			     struct i40e_dcbx_config *dcbcfg,
1189*ceebc2f3SEric Joyner 			     u16 tlvid)
1190*ceebc2f3SEric Joyner {
1191*ceebc2f3SEric Joyner 	switch (tlvid) {
1192*ceebc2f3SEric Joyner 	case I40E_IEEE_TLV_ID_ETS_CFG:
1193*ceebc2f3SEric Joyner 		i40e_add_ieee_ets_tlv(tlv, dcbcfg);
1194*ceebc2f3SEric Joyner 		break;
1195*ceebc2f3SEric Joyner 	case I40E_IEEE_TLV_ID_ETS_REC:
1196*ceebc2f3SEric Joyner 		i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
1197*ceebc2f3SEric Joyner 		break;
1198*ceebc2f3SEric Joyner 	case I40E_IEEE_TLV_ID_PFC_CFG:
1199*ceebc2f3SEric Joyner 		i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
1200*ceebc2f3SEric Joyner 		break;
1201*ceebc2f3SEric Joyner 	case I40E_IEEE_TLV_ID_APP_PRI:
1202*ceebc2f3SEric Joyner 		i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
1203*ceebc2f3SEric Joyner 		break;
1204*ceebc2f3SEric Joyner 	default:
1205*ceebc2f3SEric Joyner 		break;
1206*ceebc2f3SEric Joyner 	}
1207*ceebc2f3SEric Joyner }
1208*ceebc2f3SEric Joyner 
1209*ceebc2f3SEric Joyner  /**
1210*ceebc2f3SEric Joyner  * i40e_set_dcb_config - Set the local LLDP MIB to FW
1211*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
1212*ceebc2f3SEric Joyner  *
1213*ceebc2f3SEric Joyner  * Set DCB configuration to the Firmware
1214*ceebc2f3SEric Joyner  **/
1215*ceebc2f3SEric Joyner enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
1216*ceebc2f3SEric Joyner {
1217*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
1218*ceebc2f3SEric Joyner 	struct i40e_dcbx_config *dcbcfg;
1219*ceebc2f3SEric Joyner 	struct i40e_virt_mem mem;
1220*ceebc2f3SEric Joyner 	u8 mib_type, *lldpmib;
1221*ceebc2f3SEric Joyner 	u16 miblen;
1222*ceebc2f3SEric Joyner 
1223*ceebc2f3SEric Joyner 	/* update the hw local config */
1224*ceebc2f3SEric Joyner 	dcbcfg = &hw->local_dcbx_config;
1225*ceebc2f3SEric Joyner 	/* Allocate the LLDPDU */
1226*ceebc2f3SEric Joyner 	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
1227*ceebc2f3SEric Joyner 	if (ret)
1228*ceebc2f3SEric Joyner 		return ret;
1229*ceebc2f3SEric Joyner 
1230*ceebc2f3SEric Joyner 	mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
1231*ceebc2f3SEric Joyner 	if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
1232*ceebc2f3SEric Joyner 		mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
1233*ceebc2f3SEric Joyner 			    SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
1234*ceebc2f3SEric Joyner 	}
1235*ceebc2f3SEric Joyner 	lldpmib = (u8 *)mem.va;
1236*ceebc2f3SEric Joyner 	ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
1237*ceebc2f3SEric Joyner 	ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
1238*ceebc2f3SEric Joyner 
1239*ceebc2f3SEric Joyner 	i40e_free_virt_mem(hw, &mem);
1240*ceebc2f3SEric Joyner 	return ret;
1241*ceebc2f3SEric Joyner }
1242*ceebc2f3SEric Joyner 
1243*ceebc2f3SEric Joyner /**
1244*ceebc2f3SEric Joyner  * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1245*ceebc2f3SEric Joyner  * @hw: pointer to the hw struct
1246*ceebc2f3SEric Joyner  * @dcbcfg: store for LLDPDU data
1247*ceebc2f3SEric Joyner  *
1248*ceebc2f3SEric Joyner  * send DCB configuration to FW
1249*ceebc2f3SEric Joyner  **/
1250*ceebc2f3SEric Joyner enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
1251*ceebc2f3SEric Joyner 					      struct i40e_dcbx_config *dcbcfg)
1252*ceebc2f3SEric Joyner {
1253*ceebc2f3SEric Joyner 	u16 length, offset = 0, tlvid = I40E_TLV_ID_START;
1254*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
1255*ceebc2f3SEric Joyner 	struct i40e_lldp_org_tlv *tlv;
1256*ceebc2f3SEric Joyner 	u16 typelength;
1257*ceebc2f3SEric Joyner 
1258*ceebc2f3SEric Joyner 	tlv = (struct i40e_lldp_org_tlv *)lldpmib;
1259*ceebc2f3SEric Joyner 	while (1) {
1260*ceebc2f3SEric Joyner 		i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1261*ceebc2f3SEric Joyner 		typelength = I40E_NTOHS(tlv->typelength);
1262*ceebc2f3SEric Joyner 		length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
1263*ceebc2f3SEric Joyner 				I40E_LLDP_TLV_LEN_SHIFT);
1264*ceebc2f3SEric Joyner 		if (length)
1265*ceebc2f3SEric Joyner 			offset += length + 2;
1266*ceebc2f3SEric Joyner 		/* END TLV or beyond LLDPDU size */
1267*ceebc2f3SEric Joyner 		if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) ||
1268*ceebc2f3SEric Joyner 		    (offset > I40E_LLDPDU_SIZE))
1269*ceebc2f3SEric Joyner 			break;
1270*ceebc2f3SEric Joyner 		/* Move to next TLV */
1271*ceebc2f3SEric Joyner 		if (length)
1272*ceebc2f3SEric Joyner 			tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
1273*ceebc2f3SEric Joyner 			      sizeof(tlv->typelength) + length);
1274*ceebc2f3SEric Joyner 	}
1275*ceebc2f3SEric Joyner 	*miblen = offset;
1276*ceebc2f3SEric Joyner 	return ret;
1277*ceebc2f3SEric Joyner }
1278*ceebc2f3SEric Joyner 
1279*ceebc2f3SEric Joyner 
1280*ceebc2f3SEric Joyner /**
1281*ceebc2f3SEric Joyner  * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
1282*ceebc2f3SEric Joyner  * @hw: pointer to the HW structure
1283*ceebc2f3SEric Joyner  * @lldp_cfg: pointer to hold lldp configuration variables
1284*ceebc2f3SEric Joyner  * @module: address of the module pointer
1285*ceebc2f3SEric Joyner  * @word_offset: offset of LLDP configuration
1286*ceebc2f3SEric Joyner  *
1287*ceebc2f3SEric Joyner  * Reads the LLDP configuration data from NVM using passed addresses
1288*ceebc2f3SEric Joyner  **/
1289*ceebc2f3SEric Joyner static enum i40e_status_code _i40e_read_lldp_cfg(struct i40e_hw *hw,
1290*ceebc2f3SEric Joyner 					  struct i40e_lldp_variables *lldp_cfg,
1291*ceebc2f3SEric Joyner 					  u8 module, u32 word_offset)
1292*ceebc2f3SEric Joyner {
1293*ceebc2f3SEric Joyner 	u32 address, offset = (2 * word_offset);
1294*ceebc2f3SEric Joyner 	enum i40e_status_code ret;
1295*ceebc2f3SEric Joyner 	__le16 raw_mem;
1296*ceebc2f3SEric Joyner 	u16 mem;
1297*ceebc2f3SEric Joyner 
1298*ceebc2f3SEric Joyner 	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1299*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1300*ceebc2f3SEric Joyner 		return ret;
1301*ceebc2f3SEric Joyner 
1302*ceebc2f3SEric Joyner 	ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
1303*ceebc2f3SEric Joyner 			       TRUE, NULL);
1304*ceebc2f3SEric Joyner 	i40e_release_nvm(hw);
1305*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1306*ceebc2f3SEric Joyner 		return ret;
1307*ceebc2f3SEric Joyner 
1308*ceebc2f3SEric Joyner 	mem = LE16_TO_CPU(raw_mem);
1309*ceebc2f3SEric Joyner 	/* Check if this pointer needs to be read in word size or 4K sector
1310*ceebc2f3SEric Joyner 	 * units.
1311*ceebc2f3SEric Joyner 	 */
1312*ceebc2f3SEric Joyner 	if (mem & I40E_PTR_TYPE)
1313*ceebc2f3SEric Joyner 		address = (0x7FFF & mem) * 4096;
1314*ceebc2f3SEric Joyner 	else
1315*ceebc2f3SEric Joyner 		address = (0x7FFF & mem) * 2;
1316*ceebc2f3SEric Joyner 
1317*ceebc2f3SEric Joyner 	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1318*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1319*ceebc2f3SEric Joyner 		goto err_lldp_cfg;
1320*ceebc2f3SEric Joyner 
1321*ceebc2f3SEric Joyner 	ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
1322*ceebc2f3SEric Joyner 			       TRUE, NULL);
1323*ceebc2f3SEric Joyner 	i40e_release_nvm(hw);
1324*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1325*ceebc2f3SEric Joyner 		return ret;
1326*ceebc2f3SEric Joyner 
1327*ceebc2f3SEric Joyner 	mem = LE16_TO_CPU(raw_mem);
1328*ceebc2f3SEric Joyner 	offset = mem + word_offset;
1329*ceebc2f3SEric Joyner 	offset *= 2;
1330*ceebc2f3SEric Joyner 
1331*ceebc2f3SEric Joyner 	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1332*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1333*ceebc2f3SEric Joyner 		goto err_lldp_cfg;
1334*ceebc2f3SEric Joyner 
1335*ceebc2f3SEric Joyner 	ret = i40e_aq_read_nvm(hw, 0, address + offset,
1336*ceebc2f3SEric Joyner 			       sizeof(struct i40e_lldp_variables), lldp_cfg,
1337*ceebc2f3SEric Joyner 			       TRUE, NULL);
1338*ceebc2f3SEric Joyner 	i40e_release_nvm(hw);
1339*ceebc2f3SEric Joyner 
1340*ceebc2f3SEric Joyner err_lldp_cfg:
1341*ceebc2f3SEric Joyner 	return ret;
1342*ceebc2f3SEric Joyner }
1343*ceebc2f3SEric Joyner 
1344*ceebc2f3SEric Joyner /**
1345*ceebc2f3SEric Joyner  * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1346*ceebc2f3SEric Joyner  * @hw: pointer to the HW structure
1347*ceebc2f3SEric Joyner  * @lldp_cfg: pointer to hold lldp configuration variables
1348*ceebc2f3SEric Joyner  *
1349*ceebc2f3SEric Joyner  * Reads the LLDP configuration data from NVM
1350*ceebc2f3SEric Joyner  **/
1351*ceebc2f3SEric Joyner enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
1352*ceebc2f3SEric Joyner 					 struct i40e_lldp_variables *lldp_cfg)
1353*ceebc2f3SEric Joyner {
1354*ceebc2f3SEric Joyner 	enum i40e_status_code ret = I40E_SUCCESS;
1355*ceebc2f3SEric Joyner 	u32 mem;
1356*ceebc2f3SEric Joyner 
1357*ceebc2f3SEric Joyner 	if (!lldp_cfg)
1358*ceebc2f3SEric Joyner 		return I40E_ERR_PARAM;
1359*ceebc2f3SEric Joyner 
1360*ceebc2f3SEric Joyner 	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1361*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1362*ceebc2f3SEric Joyner 		return ret;
1363*ceebc2f3SEric Joyner 
1364*ceebc2f3SEric Joyner 	ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
1365*ceebc2f3SEric Joyner 			       &mem, TRUE, NULL);
1366*ceebc2f3SEric Joyner 	i40e_release_nvm(hw);
1367*ceebc2f3SEric Joyner 	if (ret != I40E_SUCCESS)
1368*ceebc2f3SEric Joyner 		return ret;
1369*ceebc2f3SEric Joyner 
1370*ceebc2f3SEric Joyner 	/* Read a bit that holds information whether we are running flat or
1371*ceebc2f3SEric Joyner 	 * structured NVM image. Flat image has LLDP configuration in shadow
1372*ceebc2f3SEric Joyner 	 * ram, so there is a need to pass different addresses for both cases.
1373*ceebc2f3SEric Joyner 	 */
1374*ceebc2f3SEric Joyner 	if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
1375*ceebc2f3SEric Joyner 		/* Flat NVM case */
1376*ceebc2f3SEric Joyner 		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
1377*ceebc2f3SEric Joyner 					  I40E_SR_LLDP_CFG_PTR);
1378*ceebc2f3SEric Joyner 	} else {
1379*ceebc2f3SEric Joyner 		/* Good old structured NVM image */
1380*ceebc2f3SEric Joyner 		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
1381*ceebc2f3SEric Joyner 					  I40E_NVM_LLDP_CFG_PTR);
1382*ceebc2f3SEric Joyner 	}
1383*ceebc2f3SEric Joyner 
1384*ceebc2f3SEric Joyner 	return ret;
1385*ceebc2f3SEric Joyner }
1386