1 /*******************************************************************************
3 Copyright (c) 2013 - 2014, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ***************************************************************************/
34 #include "i40e_adminq.h"
35 #include "i40e_prototype.h"
39 * i40e_get_dcbx_status
40 * @hw: pointer to the hw struct
41 * @status: Embedded DCBX Engine Status
43 * Get the DCBX status from the Firmware
45 enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
50 return I40E_ERR_PARAM;
52 reg = rd32(hw, I40E_PRTDCB_GENS);
53 *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
54 I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
60 * i40e_parse_ieee_etscfg_tlv
61 * @tlv: IEEE 802.1Qaz ETS CFG TLV
62 * @dcbcfg: Local store to update ETS CFG data
64 * Parses IEEE 802.1Qaz ETS CFG TLV
66 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
67 struct i40e_dcbx_config *dcbcfg)
69 struct i40e_ieee_ets_config *etscfg;
70 u8 *buf = tlv->tlvinfo;
75 /* First Octet post subtype
76 * --------------------------
77 * |will-|CBS | Re- | Max |
78 * |ing | |served| TCs |
79 * --------------------------
80 * |1bit | 1bit|3 bits|3bits|
82 etscfg = &dcbcfg->etscfg;
83 etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
84 I40E_IEEE_ETS_WILLING_SHIFT);
85 etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
86 I40E_IEEE_ETS_CBS_SHIFT);
87 etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
88 I40E_IEEE_ETS_MAXTC_SHIFT);
90 /* Move offset to Priority Assignment Table */
93 /* Priority Assignment Table (4 octets)
94 * Octets:| 1 | 2 | 3 | 4 |
95 * -----------------------------------------
96 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
97 * -----------------------------------------
98 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
99 * -----------------------------------------
101 for (i = 0; i < 4; i++) {
102 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
103 I40E_IEEE_ETS_PRIO_1_SHIFT);
104 etscfg->prioritytable[i * 2] = priority;
105 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
106 I40E_IEEE_ETS_PRIO_0_SHIFT);
107 etscfg->prioritytable[i * 2 + 1] = priority;
111 /* TC Bandwidth Table (8 octets)
112 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
113 * ---------------------------------
114 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
115 * ---------------------------------
117 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
118 etscfg->tcbwtable[i] = buf[offset++];
120 /* TSA Assignment Table (8 octets)
121 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
122 * ---------------------------------
123 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
124 * ---------------------------------
126 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
127 etscfg->tsatable[i] = buf[offset++];
131 * i40e_parse_ieee_etsrec_tlv
132 * @tlv: IEEE 802.1Qaz ETS REC TLV
133 * @dcbcfg: Local store to update ETS REC data
135 * Parses IEEE 802.1Qaz ETS REC TLV
137 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
138 struct i40e_dcbx_config *dcbcfg)
140 u8 *buf = tlv->tlvinfo;
145 /* Move offset to priority table */
148 /* Priority Assignment Table (4 octets)
149 * Octets:| 1 | 2 | 3 | 4 |
150 * -----------------------------------------
151 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
152 * -----------------------------------------
153 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
154 * -----------------------------------------
156 for (i = 0; i < 4; i++) {
157 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
158 I40E_IEEE_ETS_PRIO_1_SHIFT);
159 dcbcfg->etsrec.prioritytable[i*2] = priority;
160 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
161 I40E_IEEE_ETS_PRIO_0_SHIFT);
162 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
166 /* TC Bandwidth Table (8 octets)
167 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
168 * ---------------------------------
169 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
170 * ---------------------------------
172 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
173 dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
175 /* TSA Assignment Table (8 octets)
176 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
177 * ---------------------------------
178 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
179 * ---------------------------------
181 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
182 dcbcfg->etsrec.tsatable[i] = buf[offset++];
186 * i40e_parse_ieee_pfccfg_tlv
187 * @tlv: IEEE 802.1Qaz PFC CFG TLV
188 * @dcbcfg: Local store to update PFC CFG data
190 * Parses IEEE 802.1Qaz PFC CFG TLV
192 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
193 struct i40e_dcbx_config *dcbcfg)
195 u8 *buf = tlv->tlvinfo;
197 /* ----------------------------------------
198 * |will-|MBC | Re- | PFC | PFC Enable |
199 * |ing | |served| cap | |
200 * -----------------------------------------
201 * |1bit | 1bit|2 bits|4bits| 1 octet |
203 dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
204 I40E_IEEE_PFC_WILLING_SHIFT);
205 dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
206 I40E_IEEE_PFC_MBC_SHIFT);
207 dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
208 I40E_IEEE_PFC_CAP_SHIFT);
209 dcbcfg->pfc.pfcenable = buf[1];
213 * i40e_parse_ieee_app_tlv
214 * @tlv: IEEE 802.1Qaz APP TLV
215 * @dcbcfg: Local store to update APP PRIO data
217 * Parses IEEE 802.1Qaz APP PRIO TLV
219 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
220 struct i40e_dcbx_config *dcbcfg)
228 typelength = I40E_NTOHS(tlv->typelength);
229 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
230 I40E_LLDP_TLV_LEN_SHIFT);
233 /* The App priority table starts 5 octets after TLV header */
234 length -= (sizeof(tlv->ouisubtype) + 1);
236 /* Move offset to App Priority Table */
239 /* Application Priority Table (3 octets)
240 * Octets:| 1 | 2 | 3 |
241 * -----------------------------------------
242 * |Priority|Rsrvd| Sel | Protocol ID |
243 * -----------------------------------------
244 * Bits:|23 21|20 19|18 16|15 0|
245 * -----------------------------------------
247 while (offset < length) {
248 dcbcfg->app[i].priority = (u8)((buf[offset] &
249 I40E_IEEE_APP_PRIO_MASK) >>
250 I40E_IEEE_APP_PRIO_SHIFT);
251 dcbcfg->app[i].selector = (u8)((buf[offset] &
252 I40E_IEEE_APP_SEL_MASK) >>
253 I40E_IEEE_APP_SEL_SHIFT);
254 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
256 /* Move to next app */
259 if (i >= I40E_DCBX_MAX_APPS)
267 * i40e_parse_ieee_etsrec_tlv
268 * @tlv: IEEE 802.1Qaz TLV
269 * @dcbcfg: Local store to update ETS REC data
271 * Get the TLV subtype and send it to parsing function
272 * based on the subtype value
274 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
275 struct i40e_dcbx_config *dcbcfg)
280 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
281 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
282 I40E_LLDP_TLV_SUBTYPE_SHIFT);
284 case I40E_IEEE_SUBTYPE_ETS_CFG:
285 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
287 case I40E_IEEE_SUBTYPE_ETS_REC:
288 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
290 case I40E_IEEE_SUBTYPE_PFC_CFG:
291 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
293 case I40E_IEEE_SUBTYPE_APP_PRI:
294 i40e_parse_ieee_app_tlv(tlv, dcbcfg);
303 * @tlv: Organization specific TLV
304 * @dcbcfg: Local store to update ETS REC data
306 * Currently only IEEE 802.1Qaz TLV is supported, all others
309 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
310 struct i40e_dcbx_config *dcbcfg)
315 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
316 oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
317 I40E_LLDP_TLV_OUI_SHIFT);
319 case I40E_IEEE_8021QAZ_OUI:
320 i40e_parse_ieee_tlv(tlv, dcbcfg);
328 * i40e_lldp_to_dcb_config
329 * @lldpmib: LLDPDU to be parsed
330 * @dcbcfg: store for LLDPDU data
332 * Parse DCB configuration from the LLDPDU
334 enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
335 struct i40e_dcbx_config *dcbcfg)
337 enum i40e_status_code ret = I40E_SUCCESS;
338 struct i40e_lldp_org_tlv *tlv;
344 if (!lldpmib || !dcbcfg)
345 return I40E_ERR_PARAM;
347 /* set to the start of LLDPDU */
348 lldpmib += I40E_LLDP_MIB_HLEN;
349 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
351 typelength = I40E_NTOHS(tlv->typelength);
352 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
353 I40E_LLDP_TLV_TYPE_SHIFT);
354 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
355 I40E_LLDP_TLV_LEN_SHIFT);
356 offset += sizeof(typelength) + length;
358 /* END TLV or beyond LLDPDU size */
359 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
363 case I40E_TLV_TYPE_ORG:
364 i40e_parse_org_tlv(tlv, dcbcfg);
370 /* Move to next TLV */
371 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
372 sizeof(tlv->typelength) +
380 * i40e_aq_get_dcb_config
381 * @hw: pointer to the hw struct
382 * @mib_type: mib type for the query
383 * @bridgetype: bridge type for the query (remote)
384 * @dcbcfg: store for LLDPDU data
386 * Query DCB configuration from the Firmware
388 enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
390 struct i40e_dcbx_config *dcbcfg)
392 enum i40e_status_code ret = I40E_SUCCESS;
393 struct i40e_virt_mem mem;
396 /* Allocate the LLDPDU */
397 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
401 lldpmib = (u8 *)mem.va;
402 ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
403 (void *)lldpmib, I40E_LLDPDU_SIZE,
408 /* Parse LLDP MIB to get dcb configuration */
409 ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
412 i40e_free_virt_mem(hw, &mem);
417 * i40e_get_dcb_config
418 * @hw: pointer to the hw struct
420 * Get DCB configuration from the Firmware
422 enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
424 enum i40e_status_code ret = I40E_SUCCESS;
426 /* Get Local DCB Config */
427 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
428 &hw->local_dcbx_config);
432 /* Get Remote DCB Config */
433 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
434 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
435 &hw->remote_dcbx_config);
442 * @hw: pointer to the hw struct
444 * Update DCB configuration from the Firmware
446 enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw)
448 enum i40e_status_code ret = I40E_SUCCESS;
450 if (!hw->func_caps.dcb)
453 /* Get DCBX status */
454 ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
458 /* Check the DCBX Status */
459 switch (hw->dcbx_status) {
460 case I40E_DCBX_STATUS_DONE:
461 case I40E_DCBX_STATUS_IN_PROGRESS:
462 /* Get current DCBX configuration */
463 ret = i40e_get_dcb_config(hw);
465 case I40E_DCBX_STATUS_DISABLED:
467 case I40E_DCBX_STATUS_NOT_STARTED:
468 case I40E_DCBX_STATUS_MULTIPLE_PEERS:
473 /* Configure the LLDP MIB change event */
474 ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);