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);
483 * i40e_dcbx_event_handler
484 * @hw: pointer to the hw struct
485 * @e: event data to be processed (LLDPDU)
487 * Process LLDP MIB Change event from the Firmware
489 enum i40e_status_code i40e_process_lldp_event(struct i40e_hw *hw,
490 struct i40e_arq_event_info *e)
492 enum i40e_status_code ret = I40E_SUCCESS;
493 UNREFERENCED_2PARAMETER(hw, e);
499 * i40e_dcb_hw_rx_fifo_config
500 * @hw: pointer to the hw struct
501 * @ets_mode: Strict Priority or Round Robin mode
502 * @non_ets_mode: Strict Priority or Round Robin
503 * @max_exponent: Exponent to calculate max refill credits
504 * @lltc_map: Low latency TC bitmap
506 * Configure HW Rx FIFO as part of DCB configuration.
508 void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,
509 enum i40e_dcb_arbiter_mode ets_mode,
510 enum i40e_dcb_arbiter_mode non_ets_mode,
516 reg = rd32(hw, I40E_PRTDCB_RETSC);
518 reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;
519 reg |= ((u32)ets_mode << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) &
520 I40E_PRTDCB_RETSC_ETS_MODE_MASK;
522 reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
523 reg |= ((u32)non_ets_mode << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) &
524 I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
526 reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
527 reg |= (max_exponent << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) &
528 I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
530 reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;
531 reg |= (lltc_map << I40E_PRTDCB_RETSC_LLTC_SHIFT) &
532 I40E_PRTDCB_RETSC_LLTC_MASK;
533 wr32(hw, I40E_PRTDCB_RETSC, reg);
537 * i40e_dcb_hw_rx_cmd_monitor_config
538 * @hw: pointer to the hw struct
539 * @num_tc: Total number of traffic class
540 * @num_ports: Total number of ports on device
542 * Configure HW Rx command monitor as part of DCB configuration.
544 void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
545 u8 num_tc, u8 num_ports)
551 /* Set the threshold and fifo_size based on number of ports */
578 reg = rd32(hw, I40E_PRTDCB_RPPMC);
579 reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
580 reg |= (fifo_size << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) &
581 I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
582 wr32(hw, I40E_PRTDCB_RPPMC, reg);
586 * i40e_dcb_hw_pfc_config
587 * @hw: pointer to the hw struct
588 * @pfc_en: Bitmap of PFC enabled priorities
589 * @prio_tc: priority to tc assignment indexed by priority
591 * Configure HW Priority Flow Controller as part of DCB configuration.
593 void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
594 u8 pfc_en, u8 *prio_tc)
596 u16 pause_time = I40E_DEFAULT_PAUSE_TIME;
597 u16 refresh_time = pause_time/2;
598 u8 first_pfc_prio = 0;
605 /* Get Number of PFC TCs and TC2PFC map */
606 for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
607 if (pfc_en & (1 << i)) {
610 /* Set bit for the PFC TC */
611 tc2pfc |= 1 << prio_tc[i];
616 link_speed = hw->phy.link_info.link_speed;
617 switch (link_speed) {
618 case I40E_LINK_SPEED_10GB:
619 reg = rd32(hw, I40E_PRTDCB_MFLCN);
620 reg |= (1 << I40E_PRTDCB_MFLCN_DPF_SHIFT) &
621 I40E_PRTDCB_MFLCN_DPF_MASK;
622 reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;
623 reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;
625 reg |= (1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT) &
626 I40E_PRTDCB_MFLCN_RPFCM_MASK;
627 reg |= ((u32)pfc_en << I40E_PRTDCB_MFLCN_RPFCE_SHIFT) &
628 I40E_PRTDCB_MFLCN_RPFCE_MASK;
630 wr32(hw, I40E_PRTDCB_MFLCN, reg);
632 reg = rd32(hw, I40E_PRTDCB_FCCFG);
633 reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
635 reg |= (2 << I40E_PRTDCB_FCCFG_TFCE_SHIFT) &
636 I40E_PRTDCB_FCCFG_TFCE_MASK;
637 wr32(hw, I40E_PRTDCB_FCCFG, reg);
639 /* FCTTV and FCRTV to be set by default */
641 case I40E_LINK_SPEED_40GB:
642 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
643 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK;
644 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);
646 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
647 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK;
649 I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &
650 I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK;
651 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);
653 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
654 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
655 reg |= ((u32)pfc_en <<
656 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) &
657 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
658 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);
660 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
661 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
662 reg |= ((u32)pfc_en <<
663 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) &
664 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
665 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);
667 for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {
668 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));
669 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
671 reg |= ((u32)refresh_time <<
672 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) &
673 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
675 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);
678 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF
679 * for all user priorities
684 reg = rd32(hw, I40E_PRTDCB_TC2PFC);
685 reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
686 reg |= ((u32)tc2pfc << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) &
687 I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
688 wr32(hw, I40E_PRTDCB_TC2PFC, reg);
690 reg = rd32(hw, I40E_PRTDCB_RUP);
691 reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;
692 reg |= ((u32)first_pfc_prio << I40E_PRTDCB_RUP_NOVLANUP_SHIFT) &
693 I40E_PRTDCB_RUP_NOVLANUP_MASK;
694 wr32(hw, I40E_PRTDCB_RUP, reg);
696 reg = rd32(hw, I40E_PRTDCB_TDPMC);
697 reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
698 if (num_pfc_tc > 2) {
699 reg |= (1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &
700 I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
702 wr32(hw, I40E_PRTDCB_TDPMC, reg);
704 reg = rd32(hw, I40E_PRTDCB_TCPMC);
705 reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
706 if (num_pfc_tc > 2) {
707 reg |= (1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &
708 I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
710 wr32(hw, I40E_PRTDCB_TCPMC, reg);
714 * i40e_dcb_hw_set_num_tc
715 * @hw: pointer to the hw struct
716 * @num_tc: number of traffic classes
718 * Configure number of traffic classes in HW
720 void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
722 u32 reg = rd32(hw, I40E_PRTDCB_GENC);
724 reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;
725 reg |= ((u32)num_tc << I40E_PRTDCB_GENC_NUMTC_SHIFT) &
726 I40E_PRTDCB_GENC_NUMTC_MASK;
727 wr32(hw, I40E_PRTDCB_GENC, reg);
731 * i40e_dcb_hw_get_num_tc
732 * @hw: pointer to the hw struct
734 * Returns number of traffic classes configured in HW
736 u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
738 u32 reg = rd32(hw, I40E_PRTDCB_GENC);
740 return (reg >> I40E_PRTDCB_GENC_NUMTC_SHIFT) &
741 I40E_PRTDCB_GENC_NUMTC_MASK;
745 * i40e_dcb_hw_rx_ets_bw_config
746 * @hw: pointer to the hw struct
747 * @bw_share: Bandwidth share indexed per traffic class
748 * @mode: Strict Priority or Round Robin mode between UP sharing same
750 * @prio_type: TC is ETS enabled or strict priority
752 * Configure HW Rx ETS bandwidth as part of DCB configuration.
754 void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
755 u8 *mode, u8 *prio_type)
760 for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {
761 reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
762 reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK |
763 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
764 I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);
765 reg |= ((u32)bw_share[i] << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) &
766 I40E_PRTDCB_RETSTCC_BWSHARE_MASK;
767 reg |= ((u32)mode[i] << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) &
768 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK;
769 reg |= ((u32)prio_type[i] << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) &
770 I40E_PRTDCB_RETSTCC_ETSTC_MASK;
771 wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);
776 * i40e_dcb_hw_rx_ets_bw_config
777 * @hw: pointer to the hw struct
778 * @prio_tc: priority to tc assignment indexed by priority
780 * Configure HW Rx UP2TC map as part of DCB configuration.
782 void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)
786 #define I40E_UP2TC_REG(val, i) \
787 ((val << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \
788 I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)
790 reg = rd32(hw, I40E_PRTDCB_RUP2TC);
791 reg |= I40E_UP2TC_REG(prio_tc[0], 0);
792 reg |= I40E_UP2TC_REG(prio_tc[1], 1);
793 reg |= I40E_UP2TC_REG(prio_tc[2], 2);
794 reg |= I40E_UP2TC_REG(prio_tc[3], 3);
795 reg |= I40E_UP2TC_REG(prio_tc[4], 4);
796 reg |= I40E_UP2TC_REG(prio_tc[5], 5);
797 reg |= I40E_UP2TC_REG(prio_tc[6], 6);
798 reg |= I40E_UP2TC_REG(prio_tc[7], 7);
799 wr32(hw, I40E_PRTDCB_RUP2TC, reg);
803 * i40e_dcb_hw_calculate_pool_sizes
804 * @hw: pointer to the hw struct
805 * @num_ports: Number of available ports on the device
806 * @eee_enabled: EEE enabled for the given port
807 * @pfc_en: Bit map of PFC enabled traffic classes
808 * @mfs_tc: Array of max frame size for each traffic class
810 * Calculate the shared and dedicated per TC pool sizes,
811 * watermarks and threshold values.
813 void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,
814 u8 num_ports, bool eee_enabled,
815 u8 pfc_en, u32 *mfs_tc,
816 struct i40e_rx_pb_config *pb_cfg)
818 u32 pool_size[I40E_MAX_TRAFFIC_CLASS];
819 u32 high_wm[I40E_MAX_TRAFFIC_CLASS];
820 u32 low_wm[I40E_MAX_TRAFFIC_CLASS];
821 int shared_pool_size = 0; /* Need signed variable */
822 u32 total_pool_size = 0;
823 u32 port_pb_size = 0;
828 /* Get the MFS(max) for the port */
829 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
830 if (mfs_tc[i] > mfs_max)
834 pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);
836 /* Calculate effective Rx PB size per port */
837 port_pb_size = (I40E_DEVICE_RPB_SIZE/num_ports);
839 port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);
840 port_pb_size -= mfs_max;
842 /* Step 1 Calculating tc pool/shared pool sizes and watermarks */
843 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
844 if (pfc_en & (1 << i)) {
845 low_wm[i] = (2 * mfs_tc[i]) + pcirtt;
846 high_wm[i] = low_wm[i];
847 high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)
848 ? mfs_max : I40E_MAX_FRAME_SIZE);
849 pool_size[i] = high_wm[i];
850 pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,
854 pool_size[i] = (2 * mfs_tc[i]) + pcirtt;
855 high_wm[i] = pool_size[i];
857 total_pool_size += pool_size[i];
860 shared_pool_size = port_pb_size - total_pool_size;
861 if (shared_pool_size > 0) {
862 pb_cfg->shared_pool_size = shared_pool_size;
863 pb_cfg->shared_pool_high_wm = shared_pool_size;
864 pb_cfg->shared_pool_low_wm = 0;
865 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
866 pb_cfg->shared_pool_low_thresh[i] = 0;
867 pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;
868 pb_cfg->tc_pool_size[i] = pool_size[i];
869 pb_cfg->tc_pool_high_wm[i] = high_wm[i];
870 pb_cfg->tc_pool_low_wm[i] = low_wm[i];
874 i40e_debug(hw, I40E_DEBUG_DCB,
875 "The shared pool size for the port is negative %d.\n",
881 * i40e_dcb_hw_rx_pb_config
882 * @hw: pointer to the hw struct
883 * @old_pb_cfg: Existing Rx Packet buffer configuration
884 * @new_pb_cfg: New Rx Packet buffer configuration
886 * Program the Rx Packet Buffer registers.
888 void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,
889 struct i40e_rx_pb_config *old_pb_cfg,
890 struct i40e_rx_pb_config *new_pb_cfg)
897 /* Program the shared pool low water mark per port if decreasing */
898 old_val = old_pb_cfg->shared_pool_low_wm;
899 new_val = new_pb_cfg->shared_pool_low_wm;
900 if (new_val < old_val) {
901 reg = rd32(hw, I40E_PRTRPB_SLW);
902 reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
903 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
904 I40E_PRTRPB_SLW_SLW_MASK;
905 wr32(hw, I40E_PRTRPB_SLW, reg);
908 /* Program the shared pool low threshold and tc pool
909 * low water mark per TC that are decreasing.
911 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
912 old_val = old_pb_cfg->shared_pool_low_thresh[i];
913 new_val = new_pb_cfg->shared_pool_low_thresh[i];
914 if (new_val < old_val) {
915 reg = rd32(hw, I40E_PRTRPB_SLT(i));
916 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
917 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
918 I40E_PRTRPB_SLT_SLT_TCN_MASK;
919 wr32(hw, I40E_PRTRPB_SLT(i), reg);
922 old_val = old_pb_cfg->tc_pool_low_wm[i];
923 new_val = new_pb_cfg->tc_pool_low_wm[i];
924 if (new_val < old_val) {
925 reg = rd32(hw, I40E_PRTRPB_DLW(i));
926 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
927 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
928 I40E_PRTRPB_DLW_DLW_TCN_MASK;
929 wr32(hw, I40E_PRTRPB_DLW(i), reg);
933 /* Program the shared pool high water mark per port if decreasing */
934 old_val = old_pb_cfg->shared_pool_high_wm;
935 new_val = new_pb_cfg->shared_pool_high_wm;
936 if (new_val < old_val) {
937 reg = rd32(hw, I40E_PRTRPB_SHW);
938 reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
939 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
940 I40E_PRTRPB_SHW_SHW_MASK;
941 wr32(hw, I40E_PRTRPB_SHW, reg);
944 /* Program the shared pool high threshold and tc pool
945 * high water mark per TC that are decreasing.
947 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
948 old_val = old_pb_cfg->shared_pool_high_thresh[i];
949 new_val = new_pb_cfg->shared_pool_high_thresh[i];
950 if (new_val < old_val) {
951 reg = rd32(hw, I40E_PRTRPB_SHT(i));
952 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
953 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
954 I40E_PRTRPB_SHT_SHT_TCN_MASK;
955 wr32(hw, I40E_PRTRPB_SHT(i), reg);
958 old_val = old_pb_cfg->tc_pool_high_wm[i];
959 new_val = new_pb_cfg->tc_pool_high_wm[i];
960 if (new_val < old_val) {
961 reg = rd32(hw, I40E_PRTRPB_DHW(i));
962 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
963 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
964 I40E_PRTRPB_DHW_DHW_TCN_MASK;
965 wr32(hw, I40E_PRTRPB_DHW(i), reg);
969 /* Write Dedicated Pool Sizes per TC */
970 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
971 new_val = new_pb_cfg->tc_pool_size[i];
972 reg = rd32(hw, I40E_PRTRPB_DPS(i));
973 reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;
974 reg |= (new_val << I40E_PRTRPB_DPS_DPS_TCN_SHIFT) &
975 I40E_PRTRPB_DPS_DPS_TCN_MASK;
976 wr32(hw, I40E_PRTRPB_DPS(i), reg);
979 /* Write Shared Pool Size per port */
980 new_val = new_pb_cfg->shared_pool_size;
981 reg = rd32(hw, I40E_PRTRPB_SPS);
982 reg &= ~I40E_PRTRPB_SPS_SPS_MASK;
983 reg |= (new_val << I40E_PRTRPB_SPS_SPS_SHIFT) &
984 I40E_PRTRPB_SPS_SPS_MASK;
985 wr32(hw, I40E_PRTRPB_SPS, reg);
987 /* Program the shared pool low water mark per port if increasing */
988 old_val = old_pb_cfg->shared_pool_low_wm;
989 new_val = new_pb_cfg->shared_pool_low_wm;
990 if (new_val > old_val) {
991 reg = rd32(hw, I40E_PRTRPB_SLW);
992 reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
993 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
994 I40E_PRTRPB_SLW_SLW_MASK;
995 wr32(hw, I40E_PRTRPB_SLW, reg);
998 /* Program the shared pool low threshold and tc pool
999 * low water mark per TC that are increasing.
1001 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1002 old_val = old_pb_cfg->shared_pool_low_thresh[i];
1003 new_val = new_pb_cfg->shared_pool_low_thresh[i];
1004 if (new_val > old_val) {
1005 reg = rd32(hw, I40E_PRTRPB_SLT(i));
1006 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
1007 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
1008 I40E_PRTRPB_SLT_SLT_TCN_MASK;
1009 wr32(hw, I40E_PRTRPB_SLT(i), reg);
1012 old_val = old_pb_cfg->tc_pool_low_wm[i];
1013 new_val = new_pb_cfg->tc_pool_low_wm[i];
1014 if (new_val > old_val) {
1015 reg = rd32(hw, I40E_PRTRPB_DLW(i));
1016 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
1017 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
1018 I40E_PRTRPB_DLW_DLW_TCN_MASK;
1019 wr32(hw, I40E_PRTRPB_DLW(i), reg);
1023 /* Program the shared pool high water mark per port if increasing */
1024 old_val = old_pb_cfg->shared_pool_high_wm;
1025 new_val = new_pb_cfg->shared_pool_high_wm;
1026 if (new_val > old_val) {
1027 reg = rd32(hw, I40E_PRTRPB_SHW);
1028 reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
1029 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
1030 I40E_PRTRPB_SHW_SHW_MASK;
1031 wr32(hw, I40E_PRTRPB_SHW, reg);
1034 /* Program the shared pool high threshold and tc pool
1035 * high water mark per TC that are increasing.
1037 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1038 old_val = old_pb_cfg->shared_pool_high_thresh[i];
1039 new_val = new_pb_cfg->shared_pool_high_thresh[i];
1040 if (new_val > old_val) {
1041 reg = rd32(hw, I40E_PRTRPB_SHT(i));
1042 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
1043 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
1044 I40E_PRTRPB_SHT_SHT_TCN_MASK;
1045 wr32(hw, I40E_PRTRPB_SHT(i), reg);
1048 old_val = old_pb_cfg->tc_pool_high_wm[i];
1049 new_val = new_pb_cfg->tc_pool_high_wm[i];
1050 if (new_val > old_val) {
1051 reg = rd32(hw, I40E_PRTRPB_DHW(i));
1052 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
1053 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
1054 I40E_PRTRPB_DHW_DHW_TCN_MASK;
1055 wr32(hw, I40E_PRTRPB_DHW(i), reg);
1061 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1062 * @hw: pointer to the HW structure
1063 * @lldp_cfg: pointer to hold lldp configuration variables
1065 * Reads the LLDP configuration data from NVM
1067 enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
1068 struct i40e_lldp_variables *lldp_cfg)
1070 enum i40e_status_code ret = I40E_SUCCESS;
1071 struct i40e_emp_settings_module emp_ptr;
1075 return I40E_ERR_PARAM;
1077 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1078 if (ret != I40E_SUCCESS)
1081 ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, 0,
1082 sizeof(emp_ptr), (u8 *)&emp_ptr,
1084 i40e_release_nvm(hw);
1085 if (ret != I40E_SUCCESS)
1088 /* Calculate the byte offset for LLDP config pointer */
1089 offset = (2 * emp_ptr.lldp_cfg_ptr);
1090 offset += (2 * I40E_NVM_LLDP_CFG_PTR);
1091 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1092 if (ret != I40E_SUCCESS)
1095 ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, offset,
1096 sizeof(struct i40e_lldp_variables),
1099 i40e_release_nvm(hw);
1104 #endif /* I40E_DCB_SW */