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