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