162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2013 - 2021 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "i40e_adminq.h"
562306a36Sopenharmony_ci#include "i40e_prototype.h"
662306a36Sopenharmony_ci#include "i40e_dcb.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/**
962306a36Sopenharmony_ci * i40e_get_dcbx_status
1062306a36Sopenharmony_ci * @hw: pointer to the hw struct
1162306a36Sopenharmony_ci * @status: Embedded DCBX Engine Status
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Get the DCBX status from the Firmware
1462306a36Sopenharmony_ci **/
1562306a36Sopenharmony_ciint i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	u32 reg;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (!status)
2062306a36Sopenharmony_ci		return -EINVAL;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_GENS);
2362306a36Sopenharmony_ci	*status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
2462306a36Sopenharmony_ci			I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	return 0;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci * i40e_parse_ieee_etscfg_tlv
3162306a36Sopenharmony_ci * @tlv: IEEE 802.1Qaz ETS CFG TLV
3262306a36Sopenharmony_ci * @dcbcfg: Local store to update ETS CFG data
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Parses IEEE 802.1Qaz ETS CFG TLV
3562306a36Sopenharmony_ci **/
3662306a36Sopenharmony_cistatic void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
3762306a36Sopenharmony_ci				       struct i40e_dcbx_config *dcbcfg)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	struct i40e_dcb_ets_config *etscfg;
4062306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
4162306a36Sopenharmony_ci	u16 offset = 0;
4262306a36Sopenharmony_ci	u8 priority;
4362306a36Sopenharmony_ci	int i;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/* First Octet post subtype
4662306a36Sopenharmony_ci	 * --------------------------
4762306a36Sopenharmony_ci	 * |will-|CBS  | Re-  | Max |
4862306a36Sopenharmony_ci	 * |ing  |     |served| TCs |
4962306a36Sopenharmony_ci	 * --------------------------
5062306a36Sopenharmony_ci	 * |1bit | 1bit|3 bits|3bits|
5162306a36Sopenharmony_ci	 */
5262306a36Sopenharmony_ci	etscfg = &dcbcfg->etscfg;
5362306a36Sopenharmony_ci	etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
5462306a36Sopenharmony_ci			       I40E_IEEE_ETS_WILLING_SHIFT);
5562306a36Sopenharmony_ci	etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
5662306a36Sopenharmony_ci			   I40E_IEEE_ETS_CBS_SHIFT);
5762306a36Sopenharmony_ci	etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
5862306a36Sopenharmony_ci			      I40E_IEEE_ETS_MAXTC_SHIFT);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* Move offset to Priority Assignment Table */
6162306a36Sopenharmony_ci	offset++;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	/* Priority Assignment Table (4 octets)
6462306a36Sopenharmony_ci	 * Octets:|    1    |    2    |    3    |    4    |
6562306a36Sopenharmony_ci	 *        -----------------------------------------
6662306a36Sopenharmony_ci	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
6762306a36Sopenharmony_ci	 *        -----------------------------------------
6862306a36Sopenharmony_ci	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
6962306a36Sopenharmony_ci	 *        -----------------------------------------
7062306a36Sopenharmony_ci	 */
7162306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
7262306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
7362306a36Sopenharmony_ci				I40E_IEEE_ETS_PRIO_1_SHIFT);
7462306a36Sopenharmony_ci		etscfg->prioritytable[i * 2] =  priority;
7562306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
7662306a36Sopenharmony_ci				I40E_IEEE_ETS_PRIO_0_SHIFT);
7762306a36Sopenharmony_ci		etscfg->prioritytable[i * 2 + 1] = priority;
7862306a36Sopenharmony_ci		offset++;
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	/* TC Bandwidth Table (8 octets)
8262306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
8362306a36Sopenharmony_ci	 *        ---------------------------------
8462306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
8562306a36Sopenharmony_ci	 *        ---------------------------------
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
8862306a36Sopenharmony_ci		etscfg->tcbwtable[i] = buf[offset++];
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* TSA Assignment Table (8 octets)
9162306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9262306a36Sopenharmony_ci	 *        ---------------------------------
9362306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
9462306a36Sopenharmony_ci	 *        ---------------------------------
9562306a36Sopenharmony_ci	 */
9662306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
9762306a36Sopenharmony_ci		etscfg->tsatable[i] = buf[offset++];
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/**
10162306a36Sopenharmony_ci * i40e_parse_ieee_etsrec_tlv
10262306a36Sopenharmony_ci * @tlv: IEEE 802.1Qaz ETS REC TLV
10362306a36Sopenharmony_ci * @dcbcfg: Local store to update ETS REC data
10462306a36Sopenharmony_ci *
10562306a36Sopenharmony_ci * Parses IEEE 802.1Qaz ETS REC TLV
10662306a36Sopenharmony_ci **/
10762306a36Sopenharmony_cistatic void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
10862306a36Sopenharmony_ci				       struct i40e_dcbx_config *dcbcfg)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
11162306a36Sopenharmony_ci	u16 offset = 0;
11262306a36Sopenharmony_ci	u8 priority;
11362306a36Sopenharmony_ci	int i;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/* Move offset to priority table */
11662306a36Sopenharmony_ci	offset++;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* Priority Assignment Table (4 octets)
11962306a36Sopenharmony_ci	 * Octets:|    1    |    2    |    3    |    4    |
12062306a36Sopenharmony_ci	 *        -----------------------------------------
12162306a36Sopenharmony_ci	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
12262306a36Sopenharmony_ci	 *        -----------------------------------------
12362306a36Sopenharmony_ci	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
12462306a36Sopenharmony_ci	 *        -----------------------------------------
12562306a36Sopenharmony_ci	 */
12662306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
12762306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
12862306a36Sopenharmony_ci				I40E_IEEE_ETS_PRIO_1_SHIFT);
12962306a36Sopenharmony_ci		dcbcfg->etsrec.prioritytable[i*2] =  priority;
13062306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
13162306a36Sopenharmony_ci				I40E_IEEE_ETS_PRIO_0_SHIFT);
13262306a36Sopenharmony_ci		dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
13362306a36Sopenharmony_ci		offset++;
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/* TC Bandwidth Table (8 octets)
13762306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
13862306a36Sopenharmony_ci	 *        ---------------------------------
13962306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
14062306a36Sopenharmony_ci	 *        ---------------------------------
14162306a36Sopenharmony_ci	 */
14262306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
14362306a36Sopenharmony_ci		dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* TSA Assignment Table (8 octets)
14662306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
14762306a36Sopenharmony_ci	 *        ---------------------------------
14862306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
14962306a36Sopenharmony_ci	 *        ---------------------------------
15062306a36Sopenharmony_ci	 */
15162306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
15262306a36Sopenharmony_ci		dcbcfg->etsrec.tsatable[i] = buf[offset++];
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci * i40e_parse_ieee_pfccfg_tlv
15762306a36Sopenharmony_ci * @tlv: IEEE 802.1Qaz PFC CFG TLV
15862306a36Sopenharmony_ci * @dcbcfg: Local store to update PFC CFG data
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * Parses IEEE 802.1Qaz PFC CFG TLV
16162306a36Sopenharmony_ci **/
16262306a36Sopenharmony_cistatic void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
16362306a36Sopenharmony_ci				       struct i40e_dcbx_config *dcbcfg)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/* ----------------------------------------
16862306a36Sopenharmony_ci	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
16962306a36Sopenharmony_ci	 * |ing  |     |served| cap |              |
17062306a36Sopenharmony_ci	 * -----------------------------------------
17162306a36Sopenharmony_ci	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
17262306a36Sopenharmony_ci	 */
17362306a36Sopenharmony_ci	dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
17462306a36Sopenharmony_ci				   I40E_IEEE_PFC_WILLING_SHIFT);
17562306a36Sopenharmony_ci	dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
17662306a36Sopenharmony_ci			       I40E_IEEE_PFC_MBC_SHIFT);
17762306a36Sopenharmony_ci	dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
17862306a36Sopenharmony_ci				  I40E_IEEE_PFC_CAP_SHIFT);
17962306a36Sopenharmony_ci	dcbcfg->pfc.pfcenable = buf[1];
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci/**
18362306a36Sopenharmony_ci * i40e_parse_ieee_app_tlv
18462306a36Sopenharmony_ci * @tlv: IEEE 802.1Qaz APP TLV
18562306a36Sopenharmony_ci * @dcbcfg: Local store to update APP PRIO data
18662306a36Sopenharmony_ci *
18762306a36Sopenharmony_ci * Parses IEEE 802.1Qaz APP PRIO TLV
18862306a36Sopenharmony_ci **/
18962306a36Sopenharmony_cistatic void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
19062306a36Sopenharmony_ci				    struct i40e_dcbx_config *dcbcfg)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	u16 typelength;
19362306a36Sopenharmony_ci	u16 offset = 0;
19462306a36Sopenharmony_ci	u16 length;
19562306a36Sopenharmony_ci	int i = 0;
19662306a36Sopenharmony_ci	u8 *buf;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	typelength = ntohs(tlv->typelength);
19962306a36Sopenharmony_ci	length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
20062306a36Sopenharmony_ci		       I40E_LLDP_TLV_LEN_SHIFT);
20162306a36Sopenharmony_ci	buf = tlv->tlvinfo;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	/* The App priority table starts 5 octets after TLV header */
20462306a36Sopenharmony_ci	length -= (sizeof(tlv->ouisubtype) + 1);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	/* Move offset to App Priority Table */
20762306a36Sopenharmony_ci	offset++;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	/* Application Priority Table (3 octets)
21062306a36Sopenharmony_ci	 * Octets:|         1          |    2    |    3    |
21162306a36Sopenharmony_ci	 *        -----------------------------------------
21262306a36Sopenharmony_ci	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
21362306a36Sopenharmony_ci	 *        -----------------------------------------
21462306a36Sopenharmony_ci	 *   Bits:|23    21|20 19|18 16|15                0|
21562306a36Sopenharmony_ci	 *        -----------------------------------------
21662306a36Sopenharmony_ci	 */
21762306a36Sopenharmony_ci	while (offset < length) {
21862306a36Sopenharmony_ci		dcbcfg->app[i].priority = (u8)((buf[offset] &
21962306a36Sopenharmony_ci						I40E_IEEE_APP_PRIO_MASK) >>
22062306a36Sopenharmony_ci					       I40E_IEEE_APP_PRIO_SHIFT);
22162306a36Sopenharmony_ci		dcbcfg->app[i].selector = (u8)((buf[offset] &
22262306a36Sopenharmony_ci						I40E_IEEE_APP_SEL_MASK) >>
22362306a36Sopenharmony_ci					       I40E_IEEE_APP_SEL_SHIFT);
22462306a36Sopenharmony_ci		dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
22562306a36Sopenharmony_ci					     buf[offset + 2];
22662306a36Sopenharmony_ci		/* Move to next app */
22762306a36Sopenharmony_ci		offset += 3;
22862306a36Sopenharmony_ci		i++;
22962306a36Sopenharmony_ci		if (i >= I40E_DCBX_MAX_APPS)
23062306a36Sopenharmony_ci			break;
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	dcbcfg->numapps = i;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/**
23762306a36Sopenharmony_ci * i40e_parse_ieee_tlv
23862306a36Sopenharmony_ci * @tlv: IEEE 802.1Qaz TLV
23962306a36Sopenharmony_ci * @dcbcfg: Local store to update ETS REC data
24062306a36Sopenharmony_ci *
24162306a36Sopenharmony_ci * Get the TLV subtype and send it to parsing function
24262306a36Sopenharmony_ci * based on the subtype value
24362306a36Sopenharmony_ci **/
24462306a36Sopenharmony_cistatic void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
24562306a36Sopenharmony_ci				struct i40e_dcbx_config *dcbcfg)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	u32 ouisubtype;
24862306a36Sopenharmony_ci	u8 subtype;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	ouisubtype = ntohl(tlv->ouisubtype);
25162306a36Sopenharmony_ci	subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
25262306a36Sopenharmony_ci		       I40E_LLDP_TLV_SUBTYPE_SHIFT);
25362306a36Sopenharmony_ci	switch (subtype) {
25462306a36Sopenharmony_ci	case I40E_IEEE_SUBTYPE_ETS_CFG:
25562306a36Sopenharmony_ci		i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
25662306a36Sopenharmony_ci		break;
25762306a36Sopenharmony_ci	case I40E_IEEE_SUBTYPE_ETS_REC:
25862306a36Sopenharmony_ci		i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
25962306a36Sopenharmony_ci		break;
26062306a36Sopenharmony_ci	case I40E_IEEE_SUBTYPE_PFC_CFG:
26162306a36Sopenharmony_ci		i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
26262306a36Sopenharmony_ci		break;
26362306a36Sopenharmony_ci	case I40E_IEEE_SUBTYPE_APP_PRI:
26462306a36Sopenharmony_ci		i40e_parse_ieee_app_tlv(tlv, dcbcfg);
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	default:
26762306a36Sopenharmony_ci		break;
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/**
27262306a36Sopenharmony_ci * i40e_parse_cee_pgcfg_tlv
27362306a36Sopenharmony_ci * @tlv: CEE DCBX PG CFG TLV
27462306a36Sopenharmony_ci * @dcbcfg: Local store to update ETS CFG data
27562306a36Sopenharmony_ci *
27662306a36Sopenharmony_ci * Parses CEE DCBX PG CFG TLV
27762306a36Sopenharmony_ci **/
27862306a36Sopenharmony_cistatic void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
27962306a36Sopenharmony_ci				     struct i40e_dcbx_config *dcbcfg)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	struct i40e_dcb_ets_config *etscfg;
28262306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
28362306a36Sopenharmony_ci	u16 offset = 0;
28462306a36Sopenharmony_ci	u8 priority;
28562306a36Sopenharmony_ci	int i;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	etscfg = &dcbcfg->etscfg;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
29062306a36Sopenharmony_ci		etscfg->willing = 1;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	etscfg->cbs = 0;
29362306a36Sopenharmony_ci	/* Priority Group Table (4 octets)
29462306a36Sopenharmony_ci	 * Octets:|    1    |    2    |    3    |    4    |
29562306a36Sopenharmony_ci	 *        -----------------------------------------
29662306a36Sopenharmony_ci	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
29762306a36Sopenharmony_ci	 *        -----------------------------------------
29862306a36Sopenharmony_ci	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
29962306a36Sopenharmony_ci	 *        -----------------------------------------
30062306a36Sopenharmony_ci	 */
30162306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
30262306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
30362306a36Sopenharmony_ci				 I40E_CEE_PGID_PRIO_1_SHIFT);
30462306a36Sopenharmony_ci		etscfg->prioritytable[i * 2] =  priority;
30562306a36Sopenharmony_ci		priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
30662306a36Sopenharmony_ci				 I40E_CEE_PGID_PRIO_0_SHIFT);
30762306a36Sopenharmony_ci		etscfg->prioritytable[i * 2 + 1] = priority;
30862306a36Sopenharmony_ci		offset++;
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* PG Percentage Table (8 octets)
31262306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
31362306a36Sopenharmony_ci	 *        ---------------------------------
31462306a36Sopenharmony_ci	 *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
31562306a36Sopenharmony_ci	 *        ---------------------------------
31662306a36Sopenharmony_ci	 */
31762306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
31862306a36Sopenharmony_ci		etscfg->tcbwtable[i] = buf[offset++];
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* Number of TCs supported (1 octet) */
32162306a36Sopenharmony_ci	etscfg->maxtcs = buf[offset];
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci/**
32562306a36Sopenharmony_ci * i40e_parse_cee_pfccfg_tlv
32662306a36Sopenharmony_ci * @tlv: CEE DCBX PFC CFG TLV
32762306a36Sopenharmony_ci * @dcbcfg: Local store to update PFC CFG data
32862306a36Sopenharmony_ci *
32962306a36Sopenharmony_ci * Parses CEE DCBX PFC CFG TLV
33062306a36Sopenharmony_ci **/
33162306a36Sopenharmony_cistatic void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
33262306a36Sopenharmony_ci				      struct i40e_dcbx_config *dcbcfg)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
33762306a36Sopenharmony_ci		dcbcfg->pfc.willing = 1;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	/* ------------------------
34062306a36Sopenharmony_ci	 * | PFC Enable | PFC TCs |
34162306a36Sopenharmony_ci	 * ------------------------
34262306a36Sopenharmony_ci	 * | 1 octet    | 1 octet |
34362306a36Sopenharmony_ci	 */
34462306a36Sopenharmony_ci	dcbcfg->pfc.pfcenable = buf[0];
34562306a36Sopenharmony_ci	dcbcfg->pfc.pfccap = buf[1];
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci/**
34962306a36Sopenharmony_ci * i40e_parse_cee_app_tlv
35062306a36Sopenharmony_ci * @tlv: CEE DCBX APP TLV
35162306a36Sopenharmony_ci * @dcbcfg: Local store to update APP PRIO data
35262306a36Sopenharmony_ci *
35362306a36Sopenharmony_ci * Parses CEE DCBX APP PRIO TLV
35462306a36Sopenharmony_ci **/
35562306a36Sopenharmony_cistatic void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
35662306a36Sopenharmony_ci				   struct i40e_dcbx_config *dcbcfg)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	u16 length, typelength, offset = 0;
35962306a36Sopenharmony_ci	struct i40e_cee_app_prio *app;
36062306a36Sopenharmony_ci	u8 i;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	typelength = ntohs(tlv->hdr.typelen);
36362306a36Sopenharmony_ci	length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
36462306a36Sopenharmony_ci		       I40E_LLDP_TLV_LEN_SHIFT);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	dcbcfg->numapps = length / sizeof(*app);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	if (!dcbcfg->numapps)
36962306a36Sopenharmony_ci		return;
37062306a36Sopenharmony_ci	if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
37162306a36Sopenharmony_ci		dcbcfg->numapps = I40E_DCBX_MAX_APPS;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	for (i = 0; i < dcbcfg->numapps; i++) {
37462306a36Sopenharmony_ci		u8 up, selector;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci		app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
37762306a36Sopenharmony_ci		for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
37862306a36Sopenharmony_ci			if (app->prio_map & BIT(up))
37962306a36Sopenharmony_ci				break;
38062306a36Sopenharmony_ci		}
38162306a36Sopenharmony_ci		dcbcfg->app[i].priority = up;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci		/* Get Selector from lower 2 bits, and convert to IEEE */
38462306a36Sopenharmony_ci		selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
38562306a36Sopenharmony_ci		switch (selector) {
38662306a36Sopenharmony_ci		case I40E_CEE_APP_SEL_ETHTYPE:
38762306a36Sopenharmony_ci			dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
38862306a36Sopenharmony_ci			break;
38962306a36Sopenharmony_ci		case I40E_CEE_APP_SEL_TCPIP:
39062306a36Sopenharmony_ci			dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
39162306a36Sopenharmony_ci			break;
39262306a36Sopenharmony_ci		default:
39362306a36Sopenharmony_ci			/* Keep selector as it is for unknown types */
39462306a36Sopenharmony_ci			dcbcfg->app[i].selector = selector;
39562306a36Sopenharmony_ci		}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		dcbcfg->app[i].protocolid = ntohs(app->protocol);
39862306a36Sopenharmony_ci		/* Move to next app */
39962306a36Sopenharmony_ci		offset += sizeof(*app);
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci/**
40462306a36Sopenharmony_ci * i40e_parse_cee_tlv
40562306a36Sopenharmony_ci * @tlv: CEE DCBX TLV
40662306a36Sopenharmony_ci * @dcbcfg: Local store to update DCBX config data
40762306a36Sopenharmony_ci *
40862306a36Sopenharmony_ci * Get the TLV subtype and send it to parsing function
40962306a36Sopenharmony_ci * based on the subtype value
41062306a36Sopenharmony_ci **/
41162306a36Sopenharmony_cistatic void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
41262306a36Sopenharmony_ci			       struct i40e_dcbx_config *dcbcfg)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	u16 len, tlvlen, sublen, typelength;
41562306a36Sopenharmony_ci	struct i40e_cee_feat_tlv *sub_tlv;
41662306a36Sopenharmony_ci	u8 subtype, feat_tlv_count = 0;
41762306a36Sopenharmony_ci	u32 ouisubtype;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	ouisubtype = ntohl(tlv->ouisubtype);
42062306a36Sopenharmony_ci	subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
42162306a36Sopenharmony_ci		       I40E_LLDP_TLV_SUBTYPE_SHIFT);
42262306a36Sopenharmony_ci	/* Return if not CEE DCBX */
42362306a36Sopenharmony_ci	if (subtype != I40E_CEE_DCBX_TYPE)
42462306a36Sopenharmony_ci		return;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	typelength = ntohs(tlv->typelength);
42762306a36Sopenharmony_ci	tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
42862306a36Sopenharmony_ci			I40E_LLDP_TLV_LEN_SHIFT);
42962306a36Sopenharmony_ci	len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
43062306a36Sopenharmony_ci	      sizeof(struct i40e_cee_ctrl_tlv);
43162306a36Sopenharmony_ci	/* Return if no CEE DCBX Feature TLVs */
43262306a36Sopenharmony_ci	if (tlvlen <= len)
43362306a36Sopenharmony_ci		return;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
43662306a36Sopenharmony_ci	while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
43762306a36Sopenharmony_ci		typelength = ntohs(sub_tlv->hdr.typelen);
43862306a36Sopenharmony_ci		sublen = (u16)((typelength &
43962306a36Sopenharmony_ci				I40E_LLDP_TLV_LEN_MASK) >>
44062306a36Sopenharmony_ci				I40E_LLDP_TLV_LEN_SHIFT);
44162306a36Sopenharmony_ci		subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
44262306a36Sopenharmony_ci				I40E_LLDP_TLV_TYPE_SHIFT);
44362306a36Sopenharmony_ci		switch (subtype) {
44462306a36Sopenharmony_ci		case I40E_CEE_SUBTYPE_PG_CFG:
44562306a36Sopenharmony_ci			i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
44662306a36Sopenharmony_ci			break;
44762306a36Sopenharmony_ci		case I40E_CEE_SUBTYPE_PFC_CFG:
44862306a36Sopenharmony_ci			i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
44962306a36Sopenharmony_ci			break;
45062306a36Sopenharmony_ci		case I40E_CEE_SUBTYPE_APP_PRI:
45162306a36Sopenharmony_ci			i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
45262306a36Sopenharmony_ci			break;
45362306a36Sopenharmony_ci		default:
45462306a36Sopenharmony_ci			return; /* Invalid Sub-type return */
45562306a36Sopenharmony_ci		}
45662306a36Sopenharmony_ci		feat_tlv_count++;
45762306a36Sopenharmony_ci		/* Move to next sub TLV */
45862306a36Sopenharmony_ci		sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
45962306a36Sopenharmony_ci						sizeof(sub_tlv->hdr.typelen) +
46062306a36Sopenharmony_ci						sublen);
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci/**
46562306a36Sopenharmony_ci * i40e_parse_org_tlv
46662306a36Sopenharmony_ci * @tlv: Organization specific TLV
46762306a36Sopenharmony_ci * @dcbcfg: Local store to update ETS REC data
46862306a36Sopenharmony_ci *
46962306a36Sopenharmony_ci * Currently only IEEE 802.1Qaz TLV is supported, all others
47062306a36Sopenharmony_ci * will be returned
47162306a36Sopenharmony_ci **/
47262306a36Sopenharmony_cistatic void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
47362306a36Sopenharmony_ci			       struct i40e_dcbx_config *dcbcfg)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	u32 ouisubtype;
47662306a36Sopenharmony_ci	u32 oui;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	ouisubtype = ntohl(tlv->ouisubtype);
47962306a36Sopenharmony_ci	oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
48062306a36Sopenharmony_ci		    I40E_LLDP_TLV_OUI_SHIFT);
48162306a36Sopenharmony_ci	switch (oui) {
48262306a36Sopenharmony_ci	case I40E_IEEE_8021QAZ_OUI:
48362306a36Sopenharmony_ci		i40e_parse_ieee_tlv(tlv, dcbcfg);
48462306a36Sopenharmony_ci		break;
48562306a36Sopenharmony_ci	case I40E_CEE_DCBX_OUI:
48662306a36Sopenharmony_ci		i40e_parse_cee_tlv(tlv, dcbcfg);
48762306a36Sopenharmony_ci		break;
48862306a36Sopenharmony_ci	default:
48962306a36Sopenharmony_ci		break;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci/**
49462306a36Sopenharmony_ci * i40e_lldp_to_dcb_config
49562306a36Sopenharmony_ci * @lldpmib: LLDPDU to be parsed
49662306a36Sopenharmony_ci * @dcbcfg: store for LLDPDU data
49762306a36Sopenharmony_ci *
49862306a36Sopenharmony_ci * Parse DCB configuration from the LLDPDU
49962306a36Sopenharmony_ci **/
50062306a36Sopenharmony_ciint i40e_lldp_to_dcb_config(u8 *lldpmib,
50162306a36Sopenharmony_ci			    struct i40e_dcbx_config *dcbcfg)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	struct i40e_lldp_org_tlv *tlv;
50462306a36Sopenharmony_ci	u16 typelength;
50562306a36Sopenharmony_ci	u16 offset = 0;
50662306a36Sopenharmony_ci	int ret = 0;
50762306a36Sopenharmony_ci	u16 length;
50862306a36Sopenharmony_ci	u16 type;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (!lldpmib || !dcbcfg)
51162306a36Sopenharmony_ci		return -EINVAL;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	/* set to the start of LLDPDU */
51462306a36Sopenharmony_ci	lldpmib += ETH_HLEN;
51562306a36Sopenharmony_ci	tlv = (struct i40e_lldp_org_tlv *)lldpmib;
51662306a36Sopenharmony_ci	while (1) {
51762306a36Sopenharmony_ci		typelength = ntohs(tlv->typelength);
51862306a36Sopenharmony_ci		type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
51962306a36Sopenharmony_ci			     I40E_LLDP_TLV_TYPE_SHIFT);
52062306a36Sopenharmony_ci		length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
52162306a36Sopenharmony_ci			       I40E_LLDP_TLV_LEN_SHIFT);
52262306a36Sopenharmony_ci		offset += sizeof(typelength) + length;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci		/* END TLV or beyond LLDPDU size */
52562306a36Sopenharmony_ci		if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
52662306a36Sopenharmony_ci			break;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci		switch (type) {
52962306a36Sopenharmony_ci		case I40E_TLV_TYPE_ORG:
53062306a36Sopenharmony_ci			i40e_parse_org_tlv(tlv, dcbcfg);
53162306a36Sopenharmony_ci			break;
53262306a36Sopenharmony_ci		default:
53362306a36Sopenharmony_ci			break;
53462306a36Sopenharmony_ci		}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci		/* Move to next TLV */
53762306a36Sopenharmony_ci		tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
53862306a36Sopenharmony_ci						    sizeof(tlv->typelength) +
53962306a36Sopenharmony_ci						    length);
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	return ret;
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci/**
54662306a36Sopenharmony_ci * i40e_aq_get_dcb_config
54762306a36Sopenharmony_ci * @hw: pointer to the hw struct
54862306a36Sopenharmony_ci * @mib_type: mib type for the query
54962306a36Sopenharmony_ci * @bridgetype: bridge type for the query (remote)
55062306a36Sopenharmony_ci * @dcbcfg: store for LLDPDU data
55162306a36Sopenharmony_ci *
55262306a36Sopenharmony_ci * Query DCB configuration from the Firmware
55362306a36Sopenharmony_ci **/
55462306a36Sopenharmony_ciint i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
55562306a36Sopenharmony_ci			   u8 bridgetype,
55662306a36Sopenharmony_ci			   struct i40e_dcbx_config *dcbcfg)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct i40e_virt_mem mem;
55962306a36Sopenharmony_ci	int ret = 0;
56062306a36Sopenharmony_ci	u8 *lldpmib;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* Allocate the LLDPDU */
56362306a36Sopenharmony_ci	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
56462306a36Sopenharmony_ci	if (ret)
56562306a36Sopenharmony_ci		return ret;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	lldpmib = (u8 *)mem.va;
56862306a36Sopenharmony_ci	ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
56962306a36Sopenharmony_ci				   (void *)lldpmib, I40E_LLDPDU_SIZE,
57062306a36Sopenharmony_ci				   NULL, NULL, NULL);
57162306a36Sopenharmony_ci	if (ret)
57262306a36Sopenharmony_ci		goto free_mem;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	/* Parse LLDP MIB to get dcb configuration */
57562306a36Sopenharmony_ci	ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cifree_mem:
57862306a36Sopenharmony_ci	i40e_free_virt_mem(hw, &mem);
57962306a36Sopenharmony_ci	return ret;
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci/**
58362306a36Sopenharmony_ci * i40e_cee_to_dcb_v1_config
58462306a36Sopenharmony_ci * @cee_cfg: pointer to CEE v1 response configuration struct
58562306a36Sopenharmony_ci * @dcbcfg: DCB configuration struct
58662306a36Sopenharmony_ci *
58762306a36Sopenharmony_ci * Convert CEE v1 configuration from firmware to DCB configuration
58862306a36Sopenharmony_ci **/
58962306a36Sopenharmony_cistatic void i40e_cee_to_dcb_v1_config(
59062306a36Sopenharmony_ci			struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
59162306a36Sopenharmony_ci			struct i40e_dcbx_config *dcbcfg)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);
59462306a36Sopenharmony_ci	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
59562306a36Sopenharmony_ci	u8 i, tc, err;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	/* CEE PG data to ETS config */
59862306a36Sopenharmony_ci	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/* Note that the FW creates the oper_prio_tc nibbles reversed
60162306a36Sopenharmony_ci	 * from those in the CEE Priority Group sub-TLV.
60262306a36Sopenharmony_ci	 */
60362306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
60462306a36Sopenharmony_ci		tc = (u8)((cee_cfg->oper_prio_tc[i] &
60562306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_0_MASK) >>
60662306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_0_SHIFT);
60762306a36Sopenharmony_ci		dcbcfg->etscfg.prioritytable[i * 2] =  tc;
60862306a36Sopenharmony_ci		tc = (u8)((cee_cfg->oper_prio_tc[i] &
60962306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_1_MASK) >>
61062306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_1_SHIFT);
61162306a36Sopenharmony_ci		dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
61562306a36Sopenharmony_ci		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
61862306a36Sopenharmony_ci		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
61962306a36Sopenharmony_ci			/* Map it to next empty TC */
62062306a36Sopenharmony_ci			dcbcfg->etscfg.prioritytable[i] =
62162306a36Sopenharmony_ci						cee_cfg->oper_num_tc - 1;
62262306a36Sopenharmony_ci			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
62362306a36Sopenharmony_ci		} else {
62462306a36Sopenharmony_ci			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
62562306a36Sopenharmony_ci		}
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	/* CEE PFC data to ETS config */
62962306a36Sopenharmony_ci	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
63062306a36Sopenharmony_ci	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
63362306a36Sopenharmony_ci		  I40E_AQC_CEE_APP_STATUS_SHIFT;
63462306a36Sopenharmony_ci	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
63562306a36Sopenharmony_ci	/* Add APPs if Error is False */
63662306a36Sopenharmony_ci	if (!err) {
63762306a36Sopenharmony_ci		/* CEE operating configuration supports FCoE/iSCSI/FIP only */
63862306a36Sopenharmony_ci		dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		/* FCoE APP */
64162306a36Sopenharmony_ci		dcbcfg->app[0].priority =
64262306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
64362306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_FCOE_SHIFT;
64462306a36Sopenharmony_ci		dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
64562306a36Sopenharmony_ci		dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci		/* iSCSI APP */
64862306a36Sopenharmony_ci		dcbcfg->app[1].priority =
64962306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
65062306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_ISCSI_SHIFT;
65162306a36Sopenharmony_ci		dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
65262306a36Sopenharmony_ci		dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci		/* FIP APP */
65562306a36Sopenharmony_ci		dcbcfg->app[2].priority =
65662306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
65762306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_FIP_SHIFT;
65862306a36Sopenharmony_ci		dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
65962306a36Sopenharmony_ci		dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci/**
66462306a36Sopenharmony_ci * i40e_cee_to_dcb_config
66562306a36Sopenharmony_ci * @cee_cfg: pointer to CEE configuration struct
66662306a36Sopenharmony_ci * @dcbcfg: DCB configuration struct
66762306a36Sopenharmony_ci *
66862306a36Sopenharmony_ci * Convert CEE configuration from firmware to DCB configuration
66962306a36Sopenharmony_ci **/
67062306a36Sopenharmony_cistatic void i40e_cee_to_dcb_config(
67162306a36Sopenharmony_ci				struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
67262306a36Sopenharmony_ci				struct i40e_dcbx_config *dcbcfg)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
67562306a36Sopenharmony_ci	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
67662306a36Sopenharmony_ci	u8 i, tc, err, sync, oper;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	/* CEE PG data to ETS config */
67962306a36Sopenharmony_ci	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* Note that the FW creates the oper_prio_tc nibbles reversed
68262306a36Sopenharmony_ci	 * from those in the CEE Priority Group sub-TLV.
68362306a36Sopenharmony_ci	 */
68462306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
68562306a36Sopenharmony_ci		tc = (u8)((cee_cfg->oper_prio_tc[i] &
68662306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_0_MASK) >>
68762306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_0_SHIFT);
68862306a36Sopenharmony_ci		dcbcfg->etscfg.prioritytable[i * 2] =  tc;
68962306a36Sopenharmony_ci		tc = (u8)((cee_cfg->oper_prio_tc[i] &
69062306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_1_MASK) >>
69162306a36Sopenharmony_ci			 I40E_CEE_PGID_PRIO_1_SHIFT);
69262306a36Sopenharmony_ci		dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
69362306a36Sopenharmony_ci	}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
69662306a36Sopenharmony_ci		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
69962306a36Sopenharmony_ci		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
70062306a36Sopenharmony_ci			/* Map it to next empty TC */
70162306a36Sopenharmony_ci			dcbcfg->etscfg.prioritytable[i] =
70262306a36Sopenharmony_ci						cee_cfg->oper_num_tc - 1;
70362306a36Sopenharmony_ci			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
70462306a36Sopenharmony_ci		} else {
70562306a36Sopenharmony_ci			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
70662306a36Sopenharmony_ci		}
70762306a36Sopenharmony_ci	}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	/* CEE PFC data to ETS config */
71062306a36Sopenharmony_ci	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
71162306a36Sopenharmony_ci	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	i = 0;
71462306a36Sopenharmony_ci	status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
71562306a36Sopenharmony_ci		  I40E_AQC_CEE_FCOE_STATUS_SHIFT;
71662306a36Sopenharmony_ci	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
71762306a36Sopenharmony_ci	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
71862306a36Sopenharmony_ci	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
71962306a36Sopenharmony_ci	/* Add FCoE APP if Error is False and Oper/Sync is True */
72062306a36Sopenharmony_ci	if (!err && sync && oper) {
72162306a36Sopenharmony_ci		/* FCoE APP */
72262306a36Sopenharmony_ci		dcbcfg->app[i].priority =
72362306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
72462306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_FCOE_SHIFT;
72562306a36Sopenharmony_ci		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
72662306a36Sopenharmony_ci		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
72762306a36Sopenharmony_ci		i++;
72862306a36Sopenharmony_ci	}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
73162306a36Sopenharmony_ci		  I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
73262306a36Sopenharmony_ci	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
73362306a36Sopenharmony_ci	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
73462306a36Sopenharmony_ci	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
73562306a36Sopenharmony_ci	/* Add iSCSI APP if Error is False and Oper/Sync is True */
73662306a36Sopenharmony_ci	if (!err && sync && oper) {
73762306a36Sopenharmony_ci		/* iSCSI APP */
73862306a36Sopenharmony_ci		dcbcfg->app[i].priority =
73962306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
74062306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_ISCSI_SHIFT;
74162306a36Sopenharmony_ci		dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
74262306a36Sopenharmony_ci		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
74362306a36Sopenharmony_ci		i++;
74462306a36Sopenharmony_ci	}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
74762306a36Sopenharmony_ci		  I40E_AQC_CEE_FIP_STATUS_SHIFT;
74862306a36Sopenharmony_ci	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
74962306a36Sopenharmony_ci	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
75062306a36Sopenharmony_ci	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
75162306a36Sopenharmony_ci	/* Add FIP APP if Error is False and Oper/Sync is True */
75262306a36Sopenharmony_ci	if (!err && sync && oper) {
75362306a36Sopenharmony_ci		/* FIP APP */
75462306a36Sopenharmony_ci		dcbcfg->app[i].priority =
75562306a36Sopenharmony_ci			(app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
75662306a36Sopenharmony_ci			 I40E_AQC_CEE_APP_FIP_SHIFT;
75762306a36Sopenharmony_ci		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
75862306a36Sopenharmony_ci		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
75962306a36Sopenharmony_ci		i++;
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci	dcbcfg->numapps = i;
76262306a36Sopenharmony_ci}
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci/**
76562306a36Sopenharmony_ci * i40e_get_ieee_dcb_config
76662306a36Sopenharmony_ci * @hw: pointer to the hw struct
76762306a36Sopenharmony_ci *
76862306a36Sopenharmony_ci * Get IEEE mode DCB configuration from the Firmware
76962306a36Sopenharmony_ci **/
77062306a36Sopenharmony_cistatic int i40e_get_ieee_dcb_config(struct i40e_hw *hw)
77162306a36Sopenharmony_ci{
77262306a36Sopenharmony_ci	int ret = 0;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	/* IEEE mode */
77562306a36Sopenharmony_ci	hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
77662306a36Sopenharmony_ci	/* Get Local DCB Config */
77762306a36Sopenharmony_ci	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
77862306a36Sopenharmony_ci				     &hw->local_dcbx_config);
77962306a36Sopenharmony_ci	if (ret)
78062306a36Sopenharmony_ci		goto out;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	/* Get Remote DCB Config */
78362306a36Sopenharmony_ci	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
78462306a36Sopenharmony_ci				     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
78562306a36Sopenharmony_ci				     &hw->remote_dcbx_config);
78662306a36Sopenharmony_ci	/* Don't treat ENOENT as an error for Remote MIBs */
78762306a36Sopenharmony_ci	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
78862306a36Sopenharmony_ci		ret = 0;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ciout:
79162306a36Sopenharmony_ci	return ret;
79262306a36Sopenharmony_ci}
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci/**
79562306a36Sopenharmony_ci * i40e_get_dcb_config
79662306a36Sopenharmony_ci * @hw: pointer to the hw struct
79762306a36Sopenharmony_ci *
79862306a36Sopenharmony_ci * Get DCB configuration from the Firmware
79962306a36Sopenharmony_ci **/
80062306a36Sopenharmony_ciint i40e_get_dcb_config(struct i40e_hw *hw)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
80362306a36Sopenharmony_ci	struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
80462306a36Sopenharmony_ci	int ret = 0;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	/* If Firmware version < v4.33 on X710/XL710, IEEE only */
80762306a36Sopenharmony_ci	if ((hw->mac.type == I40E_MAC_XL710) &&
80862306a36Sopenharmony_ci	    (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
80962306a36Sopenharmony_ci	      (hw->aq.fw_maj_ver < 4)))
81062306a36Sopenharmony_ci		return i40e_get_ieee_dcb_config(hw);
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	/* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
81362306a36Sopenharmony_ci	if ((hw->mac.type == I40E_MAC_XL710) &&
81462306a36Sopenharmony_ci	    ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
81562306a36Sopenharmony_ci		ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
81662306a36Sopenharmony_ci						 sizeof(cee_v1_cfg), NULL);
81762306a36Sopenharmony_ci		if (!ret) {
81862306a36Sopenharmony_ci			/* CEE mode */
81962306a36Sopenharmony_ci			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
82062306a36Sopenharmony_ci			hw->local_dcbx_config.tlv_status =
82162306a36Sopenharmony_ci					le16_to_cpu(cee_v1_cfg.tlv_status);
82262306a36Sopenharmony_ci			i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
82362306a36Sopenharmony_ci						  &hw->local_dcbx_config);
82462306a36Sopenharmony_ci		}
82562306a36Sopenharmony_ci	} else {
82662306a36Sopenharmony_ci		ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
82762306a36Sopenharmony_ci						 sizeof(cee_cfg), NULL);
82862306a36Sopenharmony_ci		if (!ret) {
82962306a36Sopenharmony_ci			/* CEE mode */
83062306a36Sopenharmony_ci			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
83162306a36Sopenharmony_ci			hw->local_dcbx_config.tlv_status =
83262306a36Sopenharmony_ci					le32_to_cpu(cee_cfg.tlv_status);
83362306a36Sopenharmony_ci			i40e_cee_to_dcb_config(&cee_cfg,
83462306a36Sopenharmony_ci					       &hw->local_dcbx_config);
83562306a36Sopenharmony_ci		}
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	/* CEE mode not enabled try querying IEEE data */
83962306a36Sopenharmony_ci	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
84062306a36Sopenharmony_ci		return i40e_get_ieee_dcb_config(hw);
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	if (ret)
84362306a36Sopenharmony_ci		goto out;
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	/* Get CEE DCB Desired Config */
84662306a36Sopenharmony_ci	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
84762306a36Sopenharmony_ci				     &hw->desired_dcbx_config);
84862306a36Sopenharmony_ci	if (ret)
84962306a36Sopenharmony_ci		goto out;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	/* Get Remote DCB Config */
85262306a36Sopenharmony_ci	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
85362306a36Sopenharmony_ci				     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
85462306a36Sopenharmony_ci				     &hw->remote_dcbx_config);
85562306a36Sopenharmony_ci	/* Don't treat ENOENT as an error for Remote MIBs */
85662306a36Sopenharmony_ci	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
85762306a36Sopenharmony_ci		ret = 0;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ciout:
86062306a36Sopenharmony_ci	return ret;
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci/**
86462306a36Sopenharmony_ci * i40e_init_dcb
86562306a36Sopenharmony_ci * @hw: pointer to the hw struct
86662306a36Sopenharmony_ci * @enable_mib_change: enable mib change event
86762306a36Sopenharmony_ci *
86862306a36Sopenharmony_ci * Update DCB configuration from the Firmware
86962306a36Sopenharmony_ci **/
87062306a36Sopenharmony_ciint i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	struct i40e_lldp_variables lldp_cfg;
87362306a36Sopenharmony_ci	u8 adminstatus = 0;
87462306a36Sopenharmony_ci	int ret = 0;
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	if (!hw->func_caps.dcb)
87762306a36Sopenharmony_ci		return -EOPNOTSUPP;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* Read LLDP NVM area */
88062306a36Sopenharmony_ci	if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
88162306a36Sopenharmony_ci		u8 offset = 0;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci		if (hw->mac.type == I40E_MAC_XL710)
88462306a36Sopenharmony_ci			offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
88562306a36Sopenharmony_ci		else if (hw->mac.type == I40E_MAC_X722)
88662306a36Sopenharmony_ci			offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
88762306a36Sopenharmony_ci		else
88862306a36Sopenharmony_ci			return -EOPNOTSUPP;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci		ret = i40e_read_nvm_module_data(hw,
89162306a36Sopenharmony_ci						I40E_SR_EMP_SR_SETTINGS_PTR,
89262306a36Sopenharmony_ci						offset,
89362306a36Sopenharmony_ci						I40E_LLDP_CURRENT_STATUS_OFFSET,
89462306a36Sopenharmony_ci						I40E_LLDP_CURRENT_STATUS_SIZE,
89562306a36Sopenharmony_ci						&lldp_cfg.adminstatus);
89662306a36Sopenharmony_ci	} else {
89762306a36Sopenharmony_ci		ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
89862306a36Sopenharmony_ci	}
89962306a36Sopenharmony_ci	if (ret)
90062306a36Sopenharmony_ci		return -EBUSY;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	/* Get the LLDP AdminStatus for the current port */
90362306a36Sopenharmony_ci	adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
90462306a36Sopenharmony_ci	adminstatus &= 0xF;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	/* LLDP agent disabled */
90762306a36Sopenharmony_ci	if (!adminstatus) {
90862306a36Sopenharmony_ci		hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
90962306a36Sopenharmony_ci		return -EBUSY;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	/* Get DCBX status */
91362306a36Sopenharmony_ci	ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
91462306a36Sopenharmony_ci	if (ret)
91562306a36Sopenharmony_ci		return ret;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	/* Check the DCBX Status */
91862306a36Sopenharmony_ci	if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
91962306a36Sopenharmony_ci	    hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
92062306a36Sopenharmony_ci		/* Get current DCBX configuration */
92162306a36Sopenharmony_ci		ret = i40e_get_dcb_config(hw);
92262306a36Sopenharmony_ci		if (ret)
92362306a36Sopenharmony_ci			return ret;
92462306a36Sopenharmony_ci	} else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
92562306a36Sopenharmony_ci		return -EBUSY;
92662306a36Sopenharmony_ci	}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	/* Configure the LLDP MIB change event */
92962306a36Sopenharmony_ci	if (enable_mib_change)
93062306a36Sopenharmony_ci		ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	return ret;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/**
93662306a36Sopenharmony_ci * i40e_get_fw_lldp_status
93762306a36Sopenharmony_ci * @hw: pointer to the hw struct
93862306a36Sopenharmony_ci * @lldp_status: pointer to the status enum
93962306a36Sopenharmony_ci *
94062306a36Sopenharmony_ci * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
94162306a36Sopenharmony_ci * Status of agent is reported via @lldp_status parameter.
94262306a36Sopenharmony_ci **/
94362306a36Sopenharmony_ciint
94462306a36Sopenharmony_cii40e_get_fw_lldp_status(struct i40e_hw *hw,
94562306a36Sopenharmony_ci			enum i40e_get_fw_lldp_status_resp *lldp_status)
94662306a36Sopenharmony_ci{
94762306a36Sopenharmony_ci	struct i40e_virt_mem mem;
94862306a36Sopenharmony_ci	u8 *lldpmib;
94962306a36Sopenharmony_ci	int ret;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	if (!lldp_status)
95262306a36Sopenharmony_ci		return -EINVAL;
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	/* Allocate buffer for the LLDPDU */
95562306a36Sopenharmony_ci	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
95662306a36Sopenharmony_ci	if (ret)
95762306a36Sopenharmony_ci		return ret;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	lldpmib = (u8 *)mem.va;
96062306a36Sopenharmony_ci	ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
96162306a36Sopenharmony_ci				   I40E_LLDPDU_SIZE, NULL, NULL, NULL);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	if (!ret) {
96462306a36Sopenharmony_ci		*lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
96562306a36Sopenharmony_ci	} else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
96662306a36Sopenharmony_ci		/* MIB is not available yet but the agent is running */
96762306a36Sopenharmony_ci		*lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
96862306a36Sopenharmony_ci		ret = 0;
96962306a36Sopenharmony_ci	} else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
97062306a36Sopenharmony_ci		*lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
97162306a36Sopenharmony_ci		ret = 0;
97262306a36Sopenharmony_ci	}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	i40e_free_virt_mem(hw, &mem);
97562306a36Sopenharmony_ci	return ret;
97662306a36Sopenharmony_ci}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci/**
97962306a36Sopenharmony_ci * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
98062306a36Sopenharmony_ci * @tlv: Fill the ETS config data in IEEE format
98162306a36Sopenharmony_ci * @dcbcfg: Local store which holds the DCB Config
98262306a36Sopenharmony_ci *
98362306a36Sopenharmony_ci * Prepare IEEE 802.1Qaz ETS CFG TLV
98462306a36Sopenharmony_ci **/
98562306a36Sopenharmony_cistatic void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
98662306a36Sopenharmony_ci				  struct i40e_dcbx_config *dcbcfg)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	u8 priority0, priority1, maxtcwilling = 0;
98962306a36Sopenharmony_ci	struct i40e_dcb_ets_config *etscfg;
99062306a36Sopenharmony_ci	u16 offset = 0, typelength, i;
99162306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
99262306a36Sopenharmony_ci	u32 ouisubtype;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
99562306a36Sopenharmony_ci			I40E_IEEE_ETS_TLV_LENGTH);
99662306a36Sopenharmony_ci	tlv->typelength = htons(typelength);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
99962306a36Sopenharmony_ci			I40E_IEEE_SUBTYPE_ETS_CFG);
100062306a36Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	/* First Octet post subtype
100362306a36Sopenharmony_ci	 * --------------------------
100462306a36Sopenharmony_ci	 * |will-|CBS  | Re-  | Max |
100562306a36Sopenharmony_ci	 * |ing  |     |served| TCs |
100662306a36Sopenharmony_ci	 * --------------------------
100762306a36Sopenharmony_ci	 * |1bit | 1bit|3 bits|3bits|
100862306a36Sopenharmony_ci	 */
100962306a36Sopenharmony_ci	etscfg = &dcbcfg->etscfg;
101062306a36Sopenharmony_ci	if (etscfg->willing)
101162306a36Sopenharmony_ci		maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
101262306a36Sopenharmony_ci	maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
101362306a36Sopenharmony_ci	buf[offset] = maxtcwilling;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	/* Move offset to Priority Assignment Table */
101662306a36Sopenharmony_ci	offset++;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	/* Priority Assignment Table (4 octets)
101962306a36Sopenharmony_ci	 * Octets:|    1    |    2    |    3    |    4    |
102062306a36Sopenharmony_ci	 *        -----------------------------------------
102162306a36Sopenharmony_ci	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
102262306a36Sopenharmony_ci	 *        -----------------------------------------
102362306a36Sopenharmony_ci	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
102462306a36Sopenharmony_ci	 *        -----------------------------------------
102562306a36Sopenharmony_ci	 */
102662306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
102762306a36Sopenharmony_ci		priority0 = etscfg->prioritytable[i * 2] & 0xF;
102862306a36Sopenharmony_ci		priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
102962306a36Sopenharmony_ci		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
103062306a36Sopenharmony_ci				priority1;
103162306a36Sopenharmony_ci		offset++;
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	/* TC Bandwidth Table (8 octets)
103562306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
103662306a36Sopenharmony_ci	 *        ---------------------------------
103762306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
103862306a36Sopenharmony_ci	 *        ---------------------------------
103962306a36Sopenharmony_ci	 */
104062306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
104162306a36Sopenharmony_ci		buf[offset++] = etscfg->tcbwtable[i];
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	/* TSA Assignment Table (8 octets)
104462306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
104562306a36Sopenharmony_ci	 *        ---------------------------------
104662306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
104762306a36Sopenharmony_ci	 *        ---------------------------------
104862306a36Sopenharmony_ci	 */
104962306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
105062306a36Sopenharmony_ci		buf[offset++] = etscfg->tsatable[i];
105162306a36Sopenharmony_ci}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci/**
105462306a36Sopenharmony_ci * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
105562306a36Sopenharmony_ci * @tlv: Fill ETS Recommended TLV in IEEE format
105662306a36Sopenharmony_ci * @dcbcfg: Local store which holds the DCB Config
105762306a36Sopenharmony_ci *
105862306a36Sopenharmony_ci * Prepare IEEE 802.1Qaz ETS REC TLV
105962306a36Sopenharmony_ci **/
106062306a36Sopenharmony_cistatic void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
106162306a36Sopenharmony_ci				     struct i40e_dcbx_config *dcbcfg)
106262306a36Sopenharmony_ci{
106362306a36Sopenharmony_ci	struct i40e_dcb_ets_config *etsrec;
106462306a36Sopenharmony_ci	u16 offset = 0, typelength, i;
106562306a36Sopenharmony_ci	u8 priority0, priority1;
106662306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
106762306a36Sopenharmony_ci	u32 ouisubtype;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
107062306a36Sopenharmony_ci			I40E_IEEE_ETS_TLV_LENGTH);
107162306a36Sopenharmony_ci	tlv->typelength = htons(typelength);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
107462306a36Sopenharmony_ci			I40E_IEEE_SUBTYPE_ETS_REC);
107562306a36Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	etsrec = &dcbcfg->etsrec;
107862306a36Sopenharmony_ci	/* First Octet is reserved */
107962306a36Sopenharmony_ci	/* Move offset to Priority Assignment Table */
108062306a36Sopenharmony_ci	offset++;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	/* Priority Assignment Table (4 octets)
108362306a36Sopenharmony_ci	 * Octets:|    1    |    2    |    3    |    4    |
108462306a36Sopenharmony_ci	 *        -----------------------------------------
108562306a36Sopenharmony_ci	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
108662306a36Sopenharmony_ci	 *        -----------------------------------------
108762306a36Sopenharmony_ci	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
108862306a36Sopenharmony_ci	 *        -----------------------------------------
108962306a36Sopenharmony_ci	 */
109062306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
109162306a36Sopenharmony_ci		priority0 = etsrec->prioritytable[i * 2] & 0xF;
109262306a36Sopenharmony_ci		priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
109362306a36Sopenharmony_ci		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
109462306a36Sopenharmony_ci				priority1;
109562306a36Sopenharmony_ci		offset++;
109662306a36Sopenharmony_ci	}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	/* TC Bandwidth Table (8 octets)
109962306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
110062306a36Sopenharmony_ci	 *        ---------------------------------
110162306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
110262306a36Sopenharmony_ci	 *        ---------------------------------
110362306a36Sopenharmony_ci	 */
110462306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
110562306a36Sopenharmony_ci		buf[offset++] = etsrec->tcbwtable[i];
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	/* TSA Assignment Table (8 octets)
110862306a36Sopenharmony_ci	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
110962306a36Sopenharmony_ci	 *        ---------------------------------
111062306a36Sopenharmony_ci	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
111162306a36Sopenharmony_ci	 *        ---------------------------------
111262306a36Sopenharmony_ci	 */
111362306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
111462306a36Sopenharmony_ci		buf[offset++] = etsrec->tsatable[i];
111562306a36Sopenharmony_ci}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci/**
111862306a36Sopenharmony_ci * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
111962306a36Sopenharmony_ci * @tlv: Fill PFC TLV in IEEE format
112062306a36Sopenharmony_ci * @dcbcfg: Local store to get PFC CFG data
112162306a36Sopenharmony_ci *
112262306a36Sopenharmony_ci * Prepare IEEE 802.1Qaz PFC CFG TLV
112362306a36Sopenharmony_ci **/
112462306a36Sopenharmony_cistatic void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
112562306a36Sopenharmony_ci				  struct i40e_dcbx_config *dcbcfg)
112662306a36Sopenharmony_ci{
112762306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
112862306a36Sopenharmony_ci	u32 ouisubtype;
112962306a36Sopenharmony_ci	u16 typelength;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
113262306a36Sopenharmony_ci			I40E_IEEE_PFC_TLV_LENGTH);
113362306a36Sopenharmony_ci	tlv->typelength = htons(typelength);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
113662306a36Sopenharmony_ci			I40E_IEEE_SUBTYPE_PFC_CFG);
113762306a36Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	/* ----------------------------------------
114062306a36Sopenharmony_ci	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
114162306a36Sopenharmony_ci	 * |ing  |     |served| cap |              |
114262306a36Sopenharmony_ci	 * -----------------------------------------
114362306a36Sopenharmony_ci	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
114462306a36Sopenharmony_ci	 */
114562306a36Sopenharmony_ci	if (dcbcfg->pfc.willing)
114662306a36Sopenharmony_ci		buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	if (dcbcfg->pfc.mbc)
114962306a36Sopenharmony_ci		buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	buf[0] |= dcbcfg->pfc.pfccap & 0xF;
115262306a36Sopenharmony_ci	buf[1] = dcbcfg->pfc.pfcenable;
115362306a36Sopenharmony_ci}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci/**
115662306a36Sopenharmony_ci * i40e_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format
115762306a36Sopenharmony_ci * @tlv: Fill APP TLV in IEEE format
115862306a36Sopenharmony_ci * @dcbcfg: Local store to get APP CFG data
115962306a36Sopenharmony_ci *
116062306a36Sopenharmony_ci * Prepare IEEE 802.1Qaz APP CFG TLV
116162306a36Sopenharmony_ci **/
116262306a36Sopenharmony_cistatic void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
116362306a36Sopenharmony_ci				      struct i40e_dcbx_config *dcbcfg)
116462306a36Sopenharmony_ci{
116562306a36Sopenharmony_ci	u16 typelength, length, offset = 0;
116662306a36Sopenharmony_ci	u8 priority, selector, i = 0;
116762306a36Sopenharmony_ci	u8 *buf = tlv->tlvinfo;
116862306a36Sopenharmony_ci	u32 ouisubtype;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	/* No APP TLVs then just return */
117162306a36Sopenharmony_ci	if (dcbcfg->numapps == 0)
117262306a36Sopenharmony_ci		return;
117362306a36Sopenharmony_ci	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
117462306a36Sopenharmony_ci			I40E_IEEE_SUBTYPE_APP_PRI);
117562306a36Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	/* Move offset to App Priority Table */
117862306a36Sopenharmony_ci	offset++;
117962306a36Sopenharmony_ci	/* Application Priority Table (3 octets)
118062306a36Sopenharmony_ci	 * Octets:|         1          |    2    |    3    |
118162306a36Sopenharmony_ci	 *        -----------------------------------------
118262306a36Sopenharmony_ci	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
118362306a36Sopenharmony_ci	 *        -----------------------------------------
118462306a36Sopenharmony_ci	 *   Bits:|23    21|20 19|18 16|15                0|
118562306a36Sopenharmony_ci	 *        -----------------------------------------
118662306a36Sopenharmony_ci	 */
118762306a36Sopenharmony_ci	while (i < dcbcfg->numapps) {
118862306a36Sopenharmony_ci		priority = dcbcfg->app[i].priority & 0x7;
118962306a36Sopenharmony_ci		selector = dcbcfg->app[i].selector & 0x7;
119062306a36Sopenharmony_ci		buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
119162306a36Sopenharmony_ci		buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
119262306a36Sopenharmony_ci		buf[offset + 2] =  dcbcfg->app[i].protocolid & 0xFF;
119362306a36Sopenharmony_ci		/* Move to next app */
119462306a36Sopenharmony_ci		offset += 3;
119562306a36Sopenharmony_ci		i++;
119662306a36Sopenharmony_ci		if (i >= I40E_DCBX_MAX_APPS)
119762306a36Sopenharmony_ci			break;
119862306a36Sopenharmony_ci	}
119962306a36Sopenharmony_ci	/* length includes size of ouisubtype + 1 reserved + 3*numapps */
120062306a36Sopenharmony_ci	length = sizeof(tlv->ouisubtype) + 1 + (i * 3);
120162306a36Sopenharmony_ci	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
120262306a36Sopenharmony_ci		(length & 0x1FF));
120362306a36Sopenharmony_ci	tlv->typelength = htons(typelength);
120462306a36Sopenharmony_ci}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci/**
120762306a36Sopenharmony_ci * i40e_add_dcb_tlv - Add all IEEE TLVs
120862306a36Sopenharmony_ci * @tlv: pointer to org tlv
120962306a36Sopenharmony_ci * @dcbcfg: pointer to modified dcbx config structure *
121062306a36Sopenharmony_ci * @tlvid: tlv id to be added
121162306a36Sopenharmony_ci * add tlv information
121262306a36Sopenharmony_ci **/
121362306a36Sopenharmony_cistatic void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
121462306a36Sopenharmony_ci			     struct i40e_dcbx_config *dcbcfg,
121562306a36Sopenharmony_ci			     u16 tlvid)
121662306a36Sopenharmony_ci{
121762306a36Sopenharmony_ci	switch (tlvid) {
121862306a36Sopenharmony_ci	case I40E_IEEE_TLV_ID_ETS_CFG:
121962306a36Sopenharmony_ci		i40e_add_ieee_ets_tlv(tlv, dcbcfg);
122062306a36Sopenharmony_ci		break;
122162306a36Sopenharmony_ci	case I40E_IEEE_TLV_ID_ETS_REC:
122262306a36Sopenharmony_ci		i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
122362306a36Sopenharmony_ci		break;
122462306a36Sopenharmony_ci	case I40E_IEEE_TLV_ID_PFC_CFG:
122562306a36Sopenharmony_ci		i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
122662306a36Sopenharmony_ci		break;
122762306a36Sopenharmony_ci	case I40E_IEEE_TLV_ID_APP_PRI:
122862306a36Sopenharmony_ci		i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
122962306a36Sopenharmony_ci		break;
123062306a36Sopenharmony_ci	default:
123162306a36Sopenharmony_ci		break;
123262306a36Sopenharmony_ci	}
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci/**
123662306a36Sopenharmony_ci * i40e_set_dcb_config - Set the local LLDP MIB to FW
123762306a36Sopenharmony_ci * @hw: pointer to the hw struct
123862306a36Sopenharmony_ci *
123962306a36Sopenharmony_ci * Set DCB configuration to the Firmware
124062306a36Sopenharmony_ci **/
124162306a36Sopenharmony_ciint i40e_set_dcb_config(struct i40e_hw *hw)
124262306a36Sopenharmony_ci{
124362306a36Sopenharmony_ci	struct i40e_dcbx_config *dcbcfg;
124462306a36Sopenharmony_ci	struct i40e_virt_mem mem;
124562306a36Sopenharmony_ci	u8 mib_type, *lldpmib;
124662306a36Sopenharmony_ci	u16 miblen;
124762306a36Sopenharmony_ci	int ret;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	/* update the hw local config */
125062306a36Sopenharmony_ci	dcbcfg = &hw->local_dcbx_config;
125162306a36Sopenharmony_ci	/* Allocate the LLDPDU */
125262306a36Sopenharmony_ci	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
125362306a36Sopenharmony_ci	if (ret)
125462306a36Sopenharmony_ci		return ret;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
125762306a36Sopenharmony_ci	if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
125862306a36Sopenharmony_ci		mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
125962306a36Sopenharmony_ci			    SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
126062306a36Sopenharmony_ci	}
126162306a36Sopenharmony_ci	lldpmib = (u8 *)mem.va;
126262306a36Sopenharmony_ci	i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
126362306a36Sopenharmony_ci	ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	i40e_free_virt_mem(hw, &mem);
126662306a36Sopenharmony_ci	return ret;
126762306a36Sopenharmony_ci}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci/**
127062306a36Sopenharmony_ci * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
127162306a36Sopenharmony_ci * @lldpmib: pointer to mib to be output
127262306a36Sopenharmony_ci * @miblen: pointer to u16 for length of lldpmib
127362306a36Sopenharmony_ci * @dcbcfg: store for LLDPDU data
127462306a36Sopenharmony_ci *
127562306a36Sopenharmony_ci * send DCB configuration to FW
127662306a36Sopenharmony_ci **/
127762306a36Sopenharmony_ciint i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
127862306a36Sopenharmony_ci			    struct i40e_dcbx_config *dcbcfg)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	u16 length, offset = 0, tlvid, typelength;
128162306a36Sopenharmony_ci	struct i40e_lldp_org_tlv *tlv;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	tlv = (struct i40e_lldp_org_tlv *)lldpmib;
128462306a36Sopenharmony_ci	tlvid = I40E_TLV_ID_START;
128562306a36Sopenharmony_ci	do {
128662306a36Sopenharmony_ci		i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
128762306a36Sopenharmony_ci		typelength = ntohs(tlv->typelength);
128862306a36Sopenharmony_ci		length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
128962306a36Sopenharmony_ci				I40E_LLDP_TLV_LEN_SHIFT);
129062306a36Sopenharmony_ci		if (length)
129162306a36Sopenharmony_ci			offset += length + I40E_IEEE_TLV_HEADER_LENGTH;
129262306a36Sopenharmony_ci		/* END TLV or beyond LLDPDU size */
129362306a36Sopenharmony_ci		if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU ||
129462306a36Sopenharmony_ci		    offset >= I40E_LLDPDU_SIZE)
129562306a36Sopenharmony_ci			break;
129662306a36Sopenharmony_ci		/* Move to next TLV */
129762306a36Sopenharmony_ci		if (length)
129862306a36Sopenharmony_ci			tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
129962306a36Sopenharmony_ci			      sizeof(tlv->typelength) + length);
130062306a36Sopenharmony_ci	} while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU);
130162306a36Sopenharmony_ci	*miblen = offset;
130262306a36Sopenharmony_ci	return 0;
130362306a36Sopenharmony_ci}
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci/**
130662306a36Sopenharmony_ci * i40e_dcb_hw_rx_fifo_config
130762306a36Sopenharmony_ci * @hw: pointer to the hw struct
130862306a36Sopenharmony_ci * @ets_mode: Strict Priority or Round Robin mode
130962306a36Sopenharmony_ci * @non_ets_mode: Strict Priority or Round Robin
131062306a36Sopenharmony_ci * @max_exponent: Exponent to calculate max refill credits
131162306a36Sopenharmony_ci * @lltc_map: Low latency TC bitmap
131262306a36Sopenharmony_ci *
131362306a36Sopenharmony_ci * Configure HW Rx FIFO as part of DCB configuration.
131462306a36Sopenharmony_ci **/
131562306a36Sopenharmony_civoid i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,
131662306a36Sopenharmony_ci				enum i40e_dcb_arbiter_mode ets_mode,
131762306a36Sopenharmony_ci				enum i40e_dcb_arbiter_mode non_ets_mode,
131862306a36Sopenharmony_ci				u32 max_exponent,
131962306a36Sopenharmony_ci				u8 lltc_map)
132062306a36Sopenharmony_ci{
132162306a36Sopenharmony_ci	u32 reg = rd32(hw, I40E_PRTDCB_RETSC);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;
132462306a36Sopenharmony_ci	reg |= ((u32)ets_mode << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) &
132562306a36Sopenharmony_ci		I40E_PRTDCB_RETSC_ETS_MODE_MASK;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
132862306a36Sopenharmony_ci	reg |= ((u32)non_ets_mode << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) &
132962306a36Sopenharmony_ci		I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
133262306a36Sopenharmony_ci	reg |= (max_exponent << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) &
133362306a36Sopenharmony_ci		I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;
133662306a36Sopenharmony_ci	reg |= (lltc_map << I40E_PRTDCB_RETSC_LLTC_SHIFT) &
133762306a36Sopenharmony_ci		I40E_PRTDCB_RETSC_LLTC_MASK;
133862306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_RETSC, reg);
133962306a36Sopenharmony_ci}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci/**
134262306a36Sopenharmony_ci * i40e_dcb_hw_rx_cmd_monitor_config
134362306a36Sopenharmony_ci * @hw: pointer to the hw struct
134462306a36Sopenharmony_ci * @num_tc: Total number of traffic class
134562306a36Sopenharmony_ci * @num_ports: Total number of ports on device
134662306a36Sopenharmony_ci *
134762306a36Sopenharmony_ci * Configure HW Rx command monitor as part of DCB configuration.
134862306a36Sopenharmony_ci **/
134962306a36Sopenharmony_civoid i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
135062306a36Sopenharmony_ci				       u8 num_tc, u8 num_ports)
135162306a36Sopenharmony_ci{
135262306a36Sopenharmony_ci	u32 threshold;
135362306a36Sopenharmony_ci	u32 fifo_size;
135462306a36Sopenharmony_ci	u32 reg;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	/* Set the threshold and fifo_size based on number of ports */
135762306a36Sopenharmony_ci	switch (num_ports) {
135862306a36Sopenharmony_ci	case 1:
135962306a36Sopenharmony_ci		threshold = I40E_DCB_1_PORT_THRESHOLD;
136062306a36Sopenharmony_ci		fifo_size = I40E_DCB_1_PORT_FIFO_SIZE;
136162306a36Sopenharmony_ci		break;
136262306a36Sopenharmony_ci	case 2:
136362306a36Sopenharmony_ci		if (num_tc > 4) {
136462306a36Sopenharmony_ci			threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC;
136562306a36Sopenharmony_ci			fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC;
136662306a36Sopenharmony_ci		} else {
136762306a36Sopenharmony_ci			threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC;
136862306a36Sopenharmony_ci			fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC;
136962306a36Sopenharmony_ci		}
137062306a36Sopenharmony_ci		break;
137162306a36Sopenharmony_ci	case 4:
137262306a36Sopenharmony_ci		if (num_tc > 4) {
137362306a36Sopenharmony_ci			threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC;
137462306a36Sopenharmony_ci			fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC;
137562306a36Sopenharmony_ci		} else {
137662306a36Sopenharmony_ci			threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC;
137762306a36Sopenharmony_ci			fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC;
137862306a36Sopenharmony_ci		}
137962306a36Sopenharmony_ci		break;
138062306a36Sopenharmony_ci	default:
138162306a36Sopenharmony_ci		i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n",
138262306a36Sopenharmony_ci			   (u32)num_ports);
138362306a36Sopenharmony_ci		return;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	/* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR
138762306a36Sopenharmony_ci	 * based on the number of ports and traffic classes for a given port as
138862306a36Sopenharmony_ci	 * part of DCB configuration.
138962306a36Sopenharmony_ci	 */
139062306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRT_SWR_PM_THR);
139162306a36Sopenharmony_ci	reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
139262306a36Sopenharmony_ci	reg |= (threshold << I40E_PRT_SWR_PM_THR_THRESHOLD_SHIFT) &
139362306a36Sopenharmony_ci		I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
139462306a36Sopenharmony_ci	wr32(hw, I40E_PRT_SWR_PM_THR, reg);
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_RPPMC);
139762306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
139862306a36Sopenharmony_ci	reg |= (fifo_size << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) &
139962306a36Sopenharmony_ci		I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
140062306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_RPPMC, reg);
140162306a36Sopenharmony_ci}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci/**
140462306a36Sopenharmony_ci * i40e_dcb_hw_pfc_config
140562306a36Sopenharmony_ci * @hw: pointer to the hw struct
140662306a36Sopenharmony_ci * @pfc_en: Bitmap of PFC enabled priorities
140762306a36Sopenharmony_ci * @prio_tc: priority to tc assignment indexed by priority
140862306a36Sopenharmony_ci *
140962306a36Sopenharmony_ci * Configure HW Priority Flow Controller as part of DCB configuration.
141062306a36Sopenharmony_ci **/
141162306a36Sopenharmony_civoid i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
141262306a36Sopenharmony_ci			    u8 pfc_en, u8 *prio_tc)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2;
141562306a36Sopenharmony_ci	u32 link_speed = hw->phy.link_info.link_speed;
141662306a36Sopenharmony_ci	u8 first_pfc_prio = 0;
141762306a36Sopenharmony_ci	u8 num_pfc_tc = 0;
141862306a36Sopenharmony_ci	u8 tc2pfc = 0;
141962306a36Sopenharmony_ci	u32 reg;
142062306a36Sopenharmony_ci	u8 i;
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	/* Get Number of PFC TCs and TC2PFC map */
142362306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
142462306a36Sopenharmony_ci		if (pfc_en & BIT(i)) {
142562306a36Sopenharmony_ci			if (!first_pfc_prio)
142662306a36Sopenharmony_ci				first_pfc_prio = i;
142762306a36Sopenharmony_ci			/* Set bit for the PFC TC */
142862306a36Sopenharmony_ci			tc2pfc |= BIT(prio_tc[i]);
142962306a36Sopenharmony_ci			num_pfc_tc++;
143062306a36Sopenharmony_ci		}
143162306a36Sopenharmony_ci	}
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	switch (link_speed) {
143462306a36Sopenharmony_ci	case I40E_LINK_SPEED_10GB:
143562306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTDCB_MFLCN);
143662306a36Sopenharmony_ci		reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) &
143762306a36Sopenharmony_ci			I40E_PRTDCB_MFLCN_DPF_MASK;
143862306a36Sopenharmony_ci		reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;
143962306a36Sopenharmony_ci		reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;
144062306a36Sopenharmony_ci		if (pfc_en) {
144162306a36Sopenharmony_ci			reg |= BIT(I40E_PRTDCB_MFLCN_RPFCM_SHIFT) &
144262306a36Sopenharmony_ci				I40E_PRTDCB_MFLCN_RPFCM_MASK;
144362306a36Sopenharmony_ci			reg |= ((u32)pfc_en << I40E_PRTDCB_MFLCN_RPFCE_SHIFT) &
144462306a36Sopenharmony_ci				I40E_PRTDCB_MFLCN_RPFCE_MASK;
144562306a36Sopenharmony_ci		}
144662306a36Sopenharmony_ci		wr32(hw, I40E_PRTDCB_MFLCN, reg);
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTDCB_FCCFG);
144962306a36Sopenharmony_ci		reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
145062306a36Sopenharmony_ci		if (pfc_en)
145162306a36Sopenharmony_ci			reg |= (I40E_DCB_PFC_ENABLED <<
145262306a36Sopenharmony_ci				I40E_PRTDCB_FCCFG_TFCE_SHIFT) &
145362306a36Sopenharmony_ci				I40E_PRTDCB_FCCFG_TFCE_MASK;
145462306a36Sopenharmony_ci		wr32(hw, I40E_PRTDCB_FCCFG, reg);
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci		/* FCTTV and FCRTV to be set by default */
145762306a36Sopenharmony_ci		break;
145862306a36Sopenharmony_ci	case I40E_LINK_SPEED_40GB:
145962306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
146062306a36Sopenharmony_ci		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
146162306a36Sopenharmony_ci		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
146462306a36Sopenharmony_ci		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
146562306a36Sopenharmony_ci		reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &
146662306a36Sopenharmony_ci			I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK;
146762306a36Sopenharmony_ci		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
147062306a36Sopenharmony_ci		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
147162306a36Sopenharmony_ci		reg |= ((u32)pfc_en <<
147262306a36Sopenharmony_ci			   I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) &
147362306a36Sopenharmony_ci			I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
147462306a36Sopenharmony_ci		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
147762306a36Sopenharmony_ci		reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
147862306a36Sopenharmony_ci		reg |= ((u32)pfc_en <<
147962306a36Sopenharmony_ci			   I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) &
148062306a36Sopenharmony_ci			I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
148162306a36Sopenharmony_ci		wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci		for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {
148462306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));
148562306a36Sopenharmony_ci			reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
148662306a36Sopenharmony_ci			if (pfc_en) {
148762306a36Sopenharmony_ci				reg |= ((u32)refresh_time <<
148862306a36Sopenharmony_ci					I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) &
148962306a36Sopenharmony_ci					I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
149062306a36Sopenharmony_ci			}
149162306a36Sopenharmony_ci			wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);
149262306a36Sopenharmony_ci		}
149362306a36Sopenharmony_ci		/* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF
149462306a36Sopenharmony_ci		 * for all user priorities
149562306a36Sopenharmony_ci		 */
149662306a36Sopenharmony_ci		break;
149762306a36Sopenharmony_ci	}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_TC2PFC);
150062306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
150162306a36Sopenharmony_ci	reg |= ((u32)tc2pfc << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) &
150262306a36Sopenharmony_ci		I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
150362306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_TC2PFC, reg);
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_RUP);
150662306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;
150762306a36Sopenharmony_ci	reg |= ((u32)first_pfc_prio << I40E_PRTDCB_RUP_NOVLANUP_SHIFT) &
150862306a36Sopenharmony_ci		 I40E_PRTDCB_RUP_NOVLANUP_MASK;
150962306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_RUP, reg);
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_TDPMC);
151262306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
151362306a36Sopenharmony_ci	if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
151462306a36Sopenharmony_ci		reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &
151562306a36Sopenharmony_ci			I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
151662306a36Sopenharmony_ci	}
151762306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_TDPMC, reg);
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTDCB_TCPMC);
152062306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
152162306a36Sopenharmony_ci	if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
152262306a36Sopenharmony_ci		reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &
152362306a36Sopenharmony_ci			I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
152462306a36Sopenharmony_ci	}
152562306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_TCPMC, reg);
152662306a36Sopenharmony_ci}
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci/**
152962306a36Sopenharmony_ci * i40e_dcb_hw_set_num_tc
153062306a36Sopenharmony_ci * @hw: pointer to the hw struct
153162306a36Sopenharmony_ci * @num_tc: number of traffic classes
153262306a36Sopenharmony_ci *
153362306a36Sopenharmony_ci * Configure number of traffic classes in HW
153462306a36Sopenharmony_ci **/
153562306a36Sopenharmony_civoid i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
153662306a36Sopenharmony_ci{
153762306a36Sopenharmony_ci	u32 reg = rd32(hw, I40E_PRTDCB_GENC);
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;
154062306a36Sopenharmony_ci	reg |= ((u32)num_tc << I40E_PRTDCB_GENC_NUMTC_SHIFT) &
154162306a36Sopenharmony_ci		I40E_PRTDCB_GENC_NUMTC_MASK;
154262306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_GENC, reg);
154362306a36Sopenharmony_ci}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci/**
154662306a36Sopenharmony_ci * i40e_dcb_hw_get_num_tc
154762306a36Sopenharmony_ci * @hw: pointer to the hw struct
154862306a36Sopenharmony_ci *
154962306a36Sopenharmony_ci * Returns number of traffic classes configured in HW
155062306a36Sopenharmony_ci **/
155162306a36Sopenharmony_ciu8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
155262306a36Sopenharmony_ci{
155362306a36Sopenharmony_ci	u32 reg = rd32(hw, I40E_PRTDCB_GENC);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	return (u8)((reg & I40E_PRTDCB_GENC_NUMTC_MASK) >>
155662306a36Sopenharmony_ci		I40E_PRTDCB_GENC_NUMTC_SHIFT);
155762306a36Sopenharmony_ci}
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci/**
156062306a36Sopenharmony_ci * i40e_dcb_hw_rx_ets_bw_config
156162306a36Sopenharmony_ci * @hw: pointer to the hw struct
156262306a36Sopenharmony_ci * @bw_share: Bandwidth share indexed per traffic class
156362306a36Sopenharmony_ci * @mode: Strict Priority or Round Robin mode between UP sharing same
156462306a36Sopenharmony_ci * traffic class
156562306a36Sopenharmony_ci * @prio_type: TC is ETS enabled or strict priority
156662306a36Sopenharmony_ci *
156762306a36Sopenharmony_ci * Configure HW Rx ETS bandwidth as part of DCB configuration.
156862306a36Sopenharmony_ci **/
156962306a36Sopenharmony_civoid i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
157062306a36Sopenharmony_ci				  u8 *mode, u8 *prio_type)
157162306a36Sopenharmony_ci{
157262306a36Sopenharmony_ci	u32 reg;
157362306a36Sopenharmony_ci	u8 i;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {
157662306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
157762306a36Sopenharmony_ci		reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK     |
157862306a36Sopenharmony_ci			 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
157962306a36Sopenharmony_ci			 I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);
158062306a36Sopenharmony_ci		reg |= ((u32)bw_share[i] << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) &
158162306a36Sopenharmony_ci			 I40E_PRTDCB_RETSTCC_BWSHARE_MASK;
158262306a36Sopenharmony_ci		reg |= ((u32)mode[i] << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) &
158362306a36Sopenharmony_ci			 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK;
158462306a36Sopenharmony_ci		reg |= ((u32)prio_type[i] << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) &
158562306a36Sopenharmony_ci			 I40E_PRTDCB_RETSTCC_ETSTC_MASK;
158662306a36Sopenharmony_ci		wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);
158762306a36Sopenharmony_ci	}
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci/**
159162306a36Sopenharmony_ci * i40e_dcb_hw_rx_up2tc_config
159262306a36Sopenharmony_ci * @hw: pointer to the hw struct
159362306a36Sopenharmony_ci * @prio_tc: priority to tc assignment indexed by priority
159462306a36Sopenharmony_ci *
159562306a36Sopenharmony_ci * Configure HW Rx UP2TC map as part of DCB configuration.
159662306a36Sopenharmony_ci **/
159762306a36Sopenharmony_civoid i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)
159862306a36Sopenharmony_ci{
159962306a36Sopenharmony_ci	u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC);
160062306a36Sopenharmony_ci#define I40E_UP2TC_REG(val, i) \
160162306a36Sopenharmony_ci		(((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \
160262306a36Sopenharmony_ci		  I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[0], 0);
160562306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[1], 1);
160662306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[2], 2);
160762306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[3], 3);
160862306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[4], 4);
160962306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[5], 5);
161062306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[6], 6);
161162306a36Sopenharmony_ci	reg |= I40E_UP2TC_REG(prio_tc[7], 7);
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	wr32(hw, I40E_PRTDCB_RUP2TC, reg);
161462306a36Sopenharmony_ci}
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci/**
161762306a36Sopenharmony_ci * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes
161862306a36Sopenharmony_ci * @hw: pointer to the hw struct
161962306a36Sopenharmony_ci * @num_ports: Number of available ports on the device
162062306a36Sopenharmony_ci * @eee_enabled: EEE enabled for the given port
162162306a36Sopenharmony_ci * @pfc_en: Bit map of PFC enabled traffic classes
162262306a36Sopenharmony_ci * @mfs_tc: Array of max frame size for each traffic class
162362306a36Sopenharmony_ci * @pb_cfg: pointer to packet buffer configuration
162462306a36Sopenharmony_ci *
162562306a36Sopenharmony_ci * Calculate the shared and dedicated per TC pool sizes,
162662306a36Sopenharmony_ci * watermarks and threshold values.
162762306a36Sopenharmony_ci **/
162862306a36Sopenharmony_civoid i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,
162962306a36Sopenharmony_ci				      u8 num_ports, bool eee_enabled,
163062306a36Sopenharmony_ci				      u8 pfc_en, u32 *mfs_tc,
163162306a36Sopenharmony_ci				      struct i40e_rx_pb_config *pb_cfg)
163262306a36Sopenharmony_ci{
163362306a36Sopenharmony_ci	u32 pool_size[I40E_MAX_TRAFFIC_CLASS];
163462306a36Sopenharmony_ci	u32 high_wm[I40E_MAX_TRAFFIC_CLASS];
163562306a36Sopenharmony_ci	u32 low_wm[I40E_MAX_TRAFFIC_CLASS];
163662306a36Sopenharmony_ci	u32 total_pool_size = 0;
163762306a36Sopenharmony_ci	int shared_pool_size; /* Need signed variable */
163862306a36Sopenharmony_ci	u32 port_pb_size;
163962306a36Sopenharmony_ci	u32 mfs_max = 0;
164062306a36Sopenharmony_ci	u32 pcirtt;
164162306a36Sopenharmony_ci	u8 i;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	/* Get the MFS(max) for the port */
164462306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
164562306a36Sopenharmony_ci		if (mfs_tc[i] > mfs_max)
164662306a36Sopenharmony_ci			mfs_max = mfs_tc[i];
164762306a36Sopenharmony_ci	}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	/* Calculate effective Rx PB size per port */
165262306a36Sopenharmony_ci	port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports;
165362306a36Sopenharmony_ci	if (eee_enabled)
165462306a36Sopenharmony_ci		port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);
165562306a36Sopenharmony_ci	port_pb_size -= mfs_max;
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	/* Step 1 Calculating tc pool/shared pool sizes and watermarks */
165862306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
165962306a36Sopenharmony_ci		if (pfc_en & BIT(i)) {
166062306a36Sopenharmony_ci			low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR *
166162306a36Sopenharmony_ci				     mfs_tc[i]) + pcirtt;
166262306a36Sopenharmony_ci			high_wm[i] = low_wm[i];
166362306a36Sopenharmony_ci			high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)
166462306a36Sopenharmony_ci					? mfs_max : I40E_MAX_FRAME_SIZE);
166562306a36Sopenharmony_ci			pool_size[i] = high_wm[i];
166662306a36Sopenharmony_ci			pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,
166762306a36Sopenharmony_ci								mfs_tc[i]));
166862306a36Sopenharmony_ci		} else {
166962306a36Sopenharmony_ci			low_wm[i] = 0;
167062306a36Sopenharmony_ci			pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR *
167162306a36Sopenharmony_ci					mfs_tc[i]) + pcirtt;
167262306a36Sopenharmony_ci			high_wm[i] = pool_size[i];
167362306a36Sopenharmony_ci		}
167462306a36Sopenharmony_ci		total_pool_size += pool_size[i];
167562306a36Sopenharmony_ci	}
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	shared_pool_size = port_pb_size - total_pool_size;
167862306a36Sopenharmony_ci	if (shared_pool_size > 0) {
167962306a36Sopenharmony_ci		pb_cfg->shared_pool_size = shared_pool_size;
168062306a36Sopenharmony_ci		pb_cfg->shared_pool_high_wm = shared_pool_size;
168162306a36Sopenharmony_ci		pb_cfg->shared_pool_low_wm = 0;
168262306a36Sopenharmony_ci		for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
168362306a36Sopenharmony_ci			pb_cfg->shared_pool_low_thresh[i] = 0;
168462306a36Sopenharmony_ci			pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;
168562306a36Sopenharmony_ci			pb_cfg->tc_pool_size[i] = pool_size[i];
168662306a36Sopenharmony_ci			pb_cfg->tc_pool_high_wm[i] = high_wm[i];
168762306a36Sopenharmony_ci			pb_cfg->tc_pool_low_wm[i] = low_wm[i];
168862306a36Sopenharmony_ci		}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	} else {
169162306a36Sopenharmony_ci		i40e_debug(hw, I40E_DEBUG_DCB,
169262306a36Sopenharmony_ci			   "The shared pool size for the port is negative %d.\n",
169362306a36Sopenharmony_ci			   shared_pool_size);
169462306a36Sopenharmony_ci	}
169562306a36Sopenharmony_ci}
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci/**
169862306a36Sopenharmony_ci * i40e_dcb_hw_rx_pb_config
169962306a36Sopenharmony_ci * @hw: pointer to the hw struct
170062306a36Sopenharmony_ci * @old_pb_cfg: Existing Rx Packet buffer configuration
170162306a36Sopenharmony_ci * @new_pb_cfg: New Rx Packet buffer configuration
170262306a36Sopenharmony_ci *
170362306a36Sopenharmony_ci * Program the Rx Packet Buffer registers.
170462306a36Sopenharmony_ci **/
170562306a36Sopenharmony_civoid i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,
170662306a36Sopenharmony_ci			      struct i40e_rx_pb_config *old_pb_cfg,
170762306a36Sopenharmony_ci			      struct i40e_rx_pb_config *new_pb_cfg)
170862306a36Sopenharmony_ci{
170962306a36Sopenharmony_ci	u32 old_val;
171062306a36Sopenharmony_ci	u32 new_val;
171162306a36Sopenharmony_ci	u32 reg;
171262306a36Sopenharmony_ci	u8 i;
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	/* The Rx Packet buffer register programming needs to be done in a
171562306a36Sopenharmony_ci	 * certain order and the following code is based on that
171662306a36Sopenharmony_ci	 * requirement.
171762306a36Sopenharmony_ci	 */
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	/* Program the shared pool low water mark per port if decreasing */
172062306a36Sopenharmony_ci	old_val = old_pb_cfg->shared_pool_low_wm;
172162306a36Sopenharmony_ci	new_val = new_pb_cfg->shared_pool_low_wm;
172262306a36Sopenharmony_ci	if (new_val < old_val) {
172362306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTRPB_SLW);
172462306a36Sopenharmony_ci		reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
172562306a36Sopenharmony_ci		reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
172662306a36Sopenharmony_ci			I40E_PRTRPB_SLW_SLW_MASK;
172762306a36Sopenharmony_ci		wr32(hw, I40E_PRTRPB_SLW, reg);
172862306a36Sopenharmony_ci	}
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	/* Program the shared pool low threshold and tc pool
173162306a36Sopenharmony_ci	 * low water mark per TC that are decreasing.
173262306a36Sopenharmony_ci	 */
173362306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
173462306a36Sopenharmony_ci		old_val = old_pb_cfg->shared_pool_low_thresh[i];
173562306a36Sopenharmony_ci		new_val = new_pb_cfg->shared_pool_low_thresh[i];
173662306a36Sopenharmony_ci		if (new_val < old_val) {
173762306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_SLT(i));
173862306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
173962306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
174062306a36Sopenharmony_ci				I40E_PRTRPB_SLT_SLT_TCN_MASK;
174162306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_SLT(i), reg);
174262306a36Sopenharmony_ci		}
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci		old_val = old_pb_cfg->tc_pool_low_wm[i];
174562306a36Sopenharmony_ci		new_val = new_pb_cfg->tc_pool_low_wm[i];
174662306a36Sopenharmony_ci		if (new_val < old_val) {
174762306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_DLW(i));
174862306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
174962306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
175062306a36Sopenharmony_ci				I40E_PRTRPB_DLW_DLW_TCN_MASK;
175162306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_DLW(i), reg);
175262306a36Sopenharmony_ci		}
175362306a36Sopenharmony_ci	}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	/* Program the shared pool high water mark per port if decreasing */
175662306a36Sopenharmony_ci	old_val = old_pb_cfg->shared_pool_high_wm;
175762306a36Sopenharmony_ci	new_val = new_pb_cfg->shared_pool_high_wm;
175862306a36Sopenharmony_ci	if (new_val < old_val) {
175962306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTRPB_SHW);
176062306a36Sopenharmony_ci		reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
176162306a36Sopenharmony_ci		reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
176262306a36Sopenharmony_ci			I40E_PRTRPB_SHW_SHW_MASK;
176362306a36Sopenharmony_ci		wr32(hw, I40E_PRTRPB_SHW, reg);
176462306a36Sopenharmony_ci	}
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	/* Program the shared pool high threshold and tc pool
176762306a36Sopenharmony_ci	 * high water mark per TC that are decreasing.
176862306a36Sopenharmony_ci	 */
176962306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
177062306a36Sopenharmony_ci		old_val = old_pb_cfg->shared_pool_high_thresh[i];
177162306a36Sopenharmony_ci		new_val = new_pb_cfg->shared_pool_high_thresh[i];
177262306a36Sopenharmony_ci		if (new_val < old_val) {
177362306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_SHT(i));
177462306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
177562306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
177662306a36Sopenharmony_ci				I40E_PRTRPB_SHT_SHT_TCN_MASK;
177762306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_SHT(i), reg);
177862306a36Sopenharmony_ci		}
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci		old_val = old_pb_cfg->tc_pool_high_wm[i];
178162306a36Sopenharmony_ci		new_val = new_pb_cfg->tc_pool_high_wm[i];
178262306a36Sopenharmony_ci		if (new_val < old_val) {
178362306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_DHW(i));
178462306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
178562306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
178662306a36Sopenharmony_ci				I40E_PRTRPB_DHW_DHW_TCN_MASK;
178762306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_DHW(i), reg);
178862306a36Sopenharmony_ci		}
178962306a36Sopenharmony_ci	}
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	/* Write Dedicated Pool Sizes per TC */
179262306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
179362306a36Sopenharmony_ci		new_val = new_pb_cfg->tc_pool_size[i];
179462306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTRPB_DPS(i));
179562306a36Sopenharmony_ci		reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;
179662306a36Sopenharmony_ci		reg |= (new_val << I40E_PRTRPB_DPS_DPS_TCN_SHIFT) &
179762306a36Sopenharmony_ci			I40E_PRTRPB_DPS_DPS_TCN_MASK;
179862306a36Sopenharmony_ci		wr32(hw, I40E_PRTRPB_DPS(i), reg);
179962306a36Sopenharmony_ci	}
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	/* Write Shared Pool Size per port */
180262306a36Sopenharmony_ci	new_val = new_pb_cfg->shared_pool_size;
180362306a36Sopenharmony_ci	reg = rd32(hw, I40E_PRTRPB_SPS);
180462306a36Sopenharmony_ci	reg &= ~I40E_PRTRPB_SPS_SPS_MASK;
180562306a36Sopenharmony_ci	reg |= (new_val << I40E_PRTRPB_SPS_SPS_SHIFT) &
180662306a36Sopenharmony_ci		I40E_PRTRPB_SPS_SPS_MASK;
180762306a36Sopenharmony_ci	wr32(hw, I40E_PRTRPB_SPS, reg);
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	/* Program the shared pool low water mark per port if increasing */
181062306a36Sopenharmony_ci	old_val = old_pb_cfg->shared_pool_low_wm;
181162306a36Sopenharmony_ci	new_val = new_pb_cfg->shared_pool_low_wm;
181262306a36Sopenharmony_ci	if (new_val > old_val) {
181362306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTRPB_SLW);
181462306a36Sopenharmony_ci		reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
181562306a36Sopenharmony_ci		reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
181662306a36Sopenharmony_ci			I40E_PRTRPB_SLW_SLW_MASK;
181762306a36Sopenharmony_ci		wr32(hw, I40E_PRTRPB_SLW, reg);
181862306a36Sopenharmony_ci	}
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	/* Program the shared pool low threshold and tc pool
182162306a36Sopenharmony_ci	 * low water mark per TC that are increasing.
182262306a36Sopenharmony_ci	 */
182362306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
182462306a36Sopenharmony_ci		old_val = old_pb_cfg->shared_pool_low_thresh[i];
182562306a36Sopenharmony_ci		new_val = new_pb_cfg->shared_pool_low_thresh[i];
182662306a36Sopenharmony_ci		if (new_val > old_val) {
182762306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_SLT(i));
182862306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
182962306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
183062306a36Sopenharmony_ci				I40E_PRTRPB_SLT_SLT_TCN_MASK;
183162306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_SLT(i), reg);
183262306a36Sopenharmony_ci		}
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci		old_val = old_pb_cfg->tc_pool_low_wm[i];
183562306a36Sopenharmony_ci		new_val = new_pb_cfg->tc_pool_low_wm[i];
183662306a36Sopenharmony_ci		if (new_val > old_val) {
183762306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_DLW(i));
183862306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
183962306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
184062306a36Sopenharmony_ci				I40E_PRTRPB_DLW_DLW_TCN_MASK;
184162306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_DLW(i), reg);
184262306a36Sopenharmony_ci		}
184362306a36Sopenharmony_ci	}
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	/* Program the shared pool high water mark per port if increasing */
184662306a36Sopenharmony_ci	old_val = old_pb_cfg->shared_pool_high_wm;
184762306a36Sopenharmony_ci	new_val = new_pb_cfg->shared_pool_high_wm;
184862306a36Sopenharmony_ci	if (new_val > old_val) {
184962306a36Sopenharmony_ci		reg = rd32(hw, I40E_PRTRPB_SHW);
185062306a36Sopenharmony_ci		reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
185162306a36Sopenharmony_ci		reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
185262306a36Sopenharmony_ci			I40E_PRTRPB_SHW_SHW_MASK;
185362306a36Sopenharmony_ci		wr32(hw, I40E_PRTRPB_SHW, reg);
185462306a36Sopenharmony_ci	}
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	/* Program the shared pool high threshold and tc pool
185762306a36Sopenharmony_ci	 * high water mark per TC that are increasing.
185862306a36Sopenharmony_ci	 */
185962306a36Sopenharmony_ci	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
186062306a36Sopenharmony_ci		old_val = old_pb_cfg->shared_pool_high_thresh[i];
186162306a36Sopenharmony_ci		new_val = new_pb_cfg->shared_pool_high_thresh[i];
186262306a36Sopenharmony_ci		if (new_val > old_val) {
186362306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_SHT(i));
186462306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
186562306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
186662306a36Sopenharmony_ci				I40E_PRTRPB_SHT_SHT_TCN_MASK;
186762306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_SHT(i), reg);
186862306a36Sopenharmony_ci		}
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci		old_val = old_pb_cfg->tc_pool_high_wm[i];
187162306a36Sopenharmony_ci		new_val = new_pb_cfg->tc_pool_high_wm[i];
187262306a36Sopenharmony_ci		if (new_val > old_val) {
187362306a36Sopenharmony_ci			reg = rd32(hw, I40E_PRTRPB_DHW(i));
187462306a36Sopenharmony_ci			reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
187562306a36Sopenharmony_ci			reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
187662306a36Sopenharmony_ci				I40E_PRTRPB_DHW_DHW_TCN_MASK;
187762306a36Sopenharmony_ci			wr32(hw, I40E_PRTRPB_DHW(i), reg);
187862306a36Sopenharmony_ci		}
187962306a36Sopenharmony_ci	}
188062306a36Sopenharmony_ci}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci/**
188362306a36Sopenharmony_ci * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
188462306a36Sopenharmony_ci * @hw: pointer to the HW structure
188562306a36Sopenharmony_ci * @lldp_cfg: pointer to hold lldp configuration variables
188662306a36Sopenharmony_ci * @module: address of the module pointer
188762306a36Sopenharmony_ci * @word_offset: offset of LLDP configuration
188862306a36Sopenharmony_ci *
188962306a36Sopenharmony_ci * Reads the LLDP configuration data from NVM using passed addresses
189062306a36Sopenharmony_ci **/
189162306a36Sopenharmony_cistatic int _i40e_read_lldp_cfg(struct i40e_hw *hw,
189262306a36Sopenharmony_ci			       struct i40e_lldp_variables *lldp_cfg,
189362306a36Sopenharmony_ci			       u8 module, u32 word_offset)
189462306a36Sopenharmony_ci{
189562306a36Sopenharmony_ci	u32 address, offset = (2 * word_offset);
189662306a36Sopenharmony_ci	__le16 raw_mem;
189762306a36Sopenharmony_ci	int ret;
189862306a36Sopenharmony_ci	u16 mem;
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
190162306a36Sopenharmony_ci	if (ret)
190262306a36Sopenharmony_ci		return ret;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
190562306a36Sopenharmony_ci			       true, NULL);
190662306a36Sopenharmony_ci	i40e_release_nvm(hw);
190762306a36Sopenharmony_ci	if (ret)
190862306a36Sopenharmony_ci		return ret;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	mem = le16_to_cpu(raw_mem);
191162306a36Sopenharmony_ci	/* Check if this pointer needs to be read in word size or 4K sector
191262306a36Sopenharmony_ci	 * units.
191362306a36Sopenharmony_ci	 */
191462306a36Sopenharmony_ci	if (mem & I40E_PTR_TYPE)
191562306a36Sopenharmony_ci		address = (0x7FFF & mem) * 4096;
191662306a36Sopenharmony_ci	else
191762306a36Sopenharmony_ci		address = (0x7FFF & mem) * 2;
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
192062306a36Sopenharmony_ci	if (ret)
192162306a36Sopenharmony_ci		goto err_lldp_cfg;
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
192462306a36Sopenharmony_ci			       true, NULL);
192562306a36Sopenharmony_ci	i40e_release_nvm(hw);
192662306a36Sopenharmony_ci	if (ret)
192762306a36Sopenharmony_ci		return ret;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	mem = le16_to_cpu(raw_mem);
193062306a36Sopenharmony_ci	offset = mem + word_offset;
193162306a36Sopenharmony_ci	offset *= 2;
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_ci	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
193462306a36Sopenharmony_ci	if (ret)
193562306a36Sopenharmony_ci		goto err_lldp_cfg;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	ret = i40e_aq_read_nvm(hw, 0, address + offset,
193862306a36Sopenharmony_ci			       sizeof(struct i40e_lldp_variables), lldp_cfg,
193962306a36Sopenharmony_ci			       true, NULL);
194062306a36Sopenharmony_ci	i40e_release_nvm(hw);
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_cierr_lldp_cfg:
194362306a36Sopenharmony_ci	return ret;
194462306a36Sopenharmony_ci}
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci/**
194762306a36Sopenharmony_ci * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
194862306a36Sopenharmony_ci * @hw: pointer to the HW structure
194962306a36Sopenharmony_ci * @lldp_cfg: pointer to hold lldp configuration variables
195062306a36Sopenharmony_ci *
195162306a36Sopenharmony_ci * Reads the LLDP configuration data from NVM
195262306a36Sopenharmony_ci **/
195362306a36Sopenharmony_ciint i40e_read_lldp_cfg(struct i40e_hw *hw,
195462306a36Sopenharmony_ci		       struct i40e_lldp_variables *lldp_cfg)
195562306a36Sopenharmony_ci{
195662306a36Sopenharmony_ci	int ret = 0;
195762306a36Sopenharmony_ci	u32 mem;
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci	if (!lldp_cfg)
196062306a36Sopenharmony_ci		return -EINVAL;
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
196362306a36Sopenharmony_ci	if (ret)
196462306a36Sopenharmony_ci		return ret;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
196762306a36Sopenharmony_ci			       &mem, true, NULL);
196862306a36Sopenharmony_ci	i40e_release_nvm(hw);
196962306a36Sopenharmony_ci	if (ret)
197062306a36Sopenharmony_ci		return ret;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/* Read a bit that holds information whether we are running flat or
197362306a36Sopenharmony_ci	 * structured NVM image. Flat image has LLDP configuration in shadow
197462306a36Sopenharmony_ci	 * ram, so there is a need to pass different addresses for both cases.
197562306a36Sopenharmony_ci	 */
197662306a36Sopenharmony_ci	if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
197762306a36Sopenharmony_ci		/* Flat NVM case */
197862306a36Sopenharmony_ci		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
197962306a36Sopenharmony_ci					  I40E_SR_LLDP_CFG_PTR);
198062306a36Sopenharmony_ci	} else {
198162306a36Sopenharmony_ci		/* Good old structured NVM image */
198262306a36Sopenharmony_ci		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
198362306a36Sopenharmony_ci					  I40E_NVM_LLDP_CFG_PTR);
198462306a36Sopenharmony_ci	}
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci	return ret;
198762306a36Sopenharmony_ci}
1988