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