1ceebc2f3SEric Joyner /****************************************************************************** 2ceebc2f3SEric Joyner 3f4cc2d17SEric Joyner Copyright (c) 2013-2018, Intel Corporation 4ceebc2f3SEric Joyner All rights reserved. 5ceebc2f3SEric Joyner 6ceebc2f3SEric Joyner Redistribution and use in source and binary forms, with or without 7ceebc2f3SEric Joyner modification, are permitted provided that the following conditions are met: 8ceebc2f3SEric Joyner 9ceebc2f3SEric Joyner 1. Redistributions of source code must retain the above copyright notice, 10ceebc2f3SEric Joyner this list of conditions and the following disclaimer. 11ceebc2f3SEric Joyner 12ceebc2f3SEric Joyner 2. Redistributions in binary form must reproduce the above copyright 13ceebc2f3SEric Joyner notice, this list of conditions and the following disclaimer in the 14ceebc2f3SEric Joyner documentation and/or other materials provided with the distribution. 15ceebc2f3SEric Joyner 16ceebc2f3SEric Joyner 3. Neither the name of the Intel Corporation nor the names of its 17ceebc2f3SEric Joyner contributors may be used to endorse or promote products derived from 18ceebc2f3SEric Joyner this software without specific prior written permission. 19ceebc2f3SEric Joyner 20ceebc2f3SEric Joyner THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21ceebc2f3SEric Joyner AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22ceebc2f3SEric Joyner IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23ceebc2f3SEric Joyner ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24ceebc2f3SEric Joyner LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25ceebc2f3SEric Joyner CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26ceebc2f3SEric Joyner SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27ceebc2f3SEric Joyner INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28ceebc2f3SEric Joyner CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29ceebc2f3SEric Joyner ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30ceebc2f3SEric Joyner POSSIBILITY OF SUCH DAMAGE. 31ceebc2f3SEric Joyner 32ceebc2f3SEric Joyner ******************************************************************************/ 33ceebc2f3SEric Joyner /*$FreeBSD$*/ 34ceebc2f3SEric Joyner 35ceebc2f3SEric Joyner #include "i40e_adminq.h" 36ceebc2f3SEric Joyner #include "i40e_prototype.h" 37ceebc2f3SEric Joyner #include "i40e_dcb.h" 38ceebc2f3SEric Joyner 39ceebc2f3SEric Joyner /** 40ceebc2f3SEric Joyner * i40e_get_dcbx_status 41ceebc2f3SEric Joyner * @hw: pointer to the hw struct 42ceebc2f3SEric Joyner * @status: Embedded DCBX Engine Status 43ceebc2f3SEric Joyner * 44ceebc2f3SEric Joyner * Get the DCBX status from the Firmware 45ceebc2f3SEric Joyner **/ 46ceebc2f3SEric Joyner enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status) 47ceebc2f3SEric Joyner { 48ceebc2f3SEric Joyner u32 reg; 49ceebc2f3SEric Joyner 50ceebc2f3SEric Joyner if (!status) 51ceebc2f3SEric Joyner return I40E_ERR_PARAM; 52ceebc2f3SEric Joyner 53ceebc2f3SEric Joyner reg = rd32(hw, I40E_PRTDCB_GENS); 54ceebc2f3SEric Joyner *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >> 55ceebc2f3SEric Joyner I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT); 56ceebc2f3SEric Joyner 57ceebc2f3SEric Joyner return I40E_SUCCESS; 58ceebc2f3SEric Joyner } 59ceebc2f3SEric Joyner 60ceebc2f3SEric Joyner /** 61ceebc2f3SEric Joyner * i40e_parse_ieee_etscfg_tlv 62ceebc2f3SEric Joyner * @tlv: IEEE 802.1Qaz ETS CFG TLV 63ceebc2f3SEric Joyner * @dcbcfg: Local store to update ETS CFG data 64ceebc2f3SEric Joyner * 65ceebc2f3SEric Joyner * Parses IEEE 802.1Qaz ETS CFG TLV 66ceebc2f3SEric Joyner **/ 67ceebc2f3SEric Joyner static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv, 68ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 69ceebc2f3SEric Joyner { 70ceebc2f3SEric Joyner struct i40e_dcb_ets_config *etscfg; 71ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 72ceebc2f3SEric Joyner u16 offset = 0; 73ceebc2f3SEric Joyner u8 priority; 74ceebc2f3SEric Joyner int i; 75ceebc2f3SEric Joyner 76ceebc2f3SEric Joyner /* First Octet post subtype 77ceebc2f3SEric Joyner * -------------------------- 78ceebc2f3SEric Joyner * |will-|CBS | Re- | Max | 79ceebc2f3SEric Joyner * |ing | |served| TCs | 80ceebc2f3SEric Joyner * -------------------------- 81ceebc2f3SEric Joyner * |1bit | 1bit|3 bits|3bits| 82ceebc2f3SEric Joyner */ 83ceebc2f3SEric Joyner etscfg = &dcbcfg->etscfg; 84ceebc2f3SEric Joyner etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >> 85ceebc2f3SEric Joyner I40E_IEEE_ETS_WILLING_SHIFT); 86ceebc2f3SEric Joyner etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >> 87ceebc2f3SEric Joyner I40E_IEEE_ETS_CBS_SHIFT); 88ceebc2f3SEric Joyner etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >> 89ceebc2f3SEric Joyner I40E_IEEE_ETS_MAXTC_SHIFT); 90ceebc2f3SEric Joyner 91ceebc2f3SEric Joyner /* Move offset to Priority Assignment Table */ 92ceebc2f3SEric Joyner offset++; 93ceebc2f3SEric Joyner 94ceebc2f3SEric Joyner /* Priority Assignment Table (4 octets) 95ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 96ceebc2f3SEric Joyner * ----------------------------------------- 97ceebc2f3SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 98ceebc2f3SEric Joyner * ----------------------------------------- 99ceebc2f3SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 100ceebc2f3SEric Joyner * ----------------------------------------- 101ceebc2f3SEric Joyner */ 102ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 103ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> 104ceebc2f3SEric Joyner I40E_IEEE_ETS_PRIO_1_SHIFT); 105ceebc2f3SEric Joyner etscfg->prioritytable[i * 2] = priority; 106ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> 107ceebc2f3SEric Joyner I40E_IEEE_ETS_PRIO_0_SHIFT); 108ceebc2f3SEric Joyner etscfg->prioritytable[i * 2 + 1] = priority; 109ceebc2f3SEric Joyner offset++; 110ceebc2f3SEric Joyner } 111ceebc2f3SEric Joyner 112ceebc2f3SEric Joyner /* TC Bandwidth Table (8 octets) 113ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 114ceebc2f3SEric Joyner * --------------------------------- 115ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 116ceebc2f3SEric Joyner * --------------------------------- 117ceebc2f3SEric Joyner */ 118ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 119ceebc2f3SEric Joyner etscfg->tcbwtable[i] = buf[offset++]; 120ceebc2f3SEric Joyner 121ceebc2f3SEric Joyner /* TSA Assignment Table (8 octets) 122ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 123ceebc2f3SEric Joyner * --------------------------------- 124ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 125ceebc2f3SEric Joyner * --------------------------------- 126ceebc2f3SEric Joyner */ 127ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 128ceebc2f3SEric Joyner etscfg->tsatable[i] = buf[offset++]; 129ceebc2f3SEric Joyner } 130ceebc2f3SEric Joyner 131ceebc2f3SEric Joyner /** 132ceebc2f3SEric Joyner * i40e_parse_ieee_etsrec_tlv 133ceebc2f3SEric Joyner * @tlv: IEEE 802.1Qaz ETS REC TLV 134ceebc2f3SEric Joyner * @dcbcfg: Local store to update ETS REC data 135ceebc2f3SEric Joyner * 136ceebc2f3SEric Joyner * Parses IEEE 802.1Qaz ETS REC TLV 137ceebc2f3SEric Joyner **/ 138ceebc2f3SEric Joyner static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv, 139ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 140ceebc2f3SEric Joyner { 141ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 142ceebc2f3SEric Joyner u16 offset = 0; 143ceebc2f3SEric Joyner u8 priority; 144ceebc2f3SEric Joyner int i; 145ceebc2f3SEric Joyner 146ceebc2f3SEric Joyner /* Move offset to priority table */ 147ceebc2f3SEric Joyner offset++; 148ceebc2f3SEric Joyner 149ceebc2f3SEric Joyner /* Priority Assignment Table (4 octets) 150ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 151ceebc2f3SEric Joyner * ----------------------------------------- 152ceebc2f3SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 153ceebc2f3SEric Joyner * ----------------------------------------- 154ceebc2f3SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 155ceebc2f3SEric Joyner * ----------------------------------------- 156ceebc2f3SEric Joyner */ 157ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 158ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> 159ceebc2f3SEric Joyner I40E_IEEE_ETS_PRIO_1_SHIFT); 160ceebc2f3SEric Joyner dcbcfg->etsrec.prioritytable[i*2] = priority; 161ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> 162ceebc2f3SEric Joyner I40E_IEEE_ETS_PRIO_0_SHIFT); 163ceebc2f3SEric Joyner dcbcfg->etsrec.prioritytable[i*2 + 1] = priority; 164ceebc2f3SEric Joyner offset++; 165ceebc2f3SEric Joyner } 166ceebc2f3SEric Joyner 167ceebc2f3SEric Joyner /* TC Bandwidth Table (8 octets) 168ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 169ceebc2f3SEric Joyner * --------------------------------- 170ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 171ceebc2f3SEric Joyner * --------------------------------- 172ceebc2f3SEric Joyner */ 173ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 174ceebc2f3SEric Joyner dcbcfg->etsrec.tcbwtable[i] = buf[offset++]; 175ceebc2f3SEric Joyner 176ceebc2f3SEric Joyner /* TSA Assignment Table (8 octets) 177ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 178ceebc2f3SEric Joyner * --------------------------------- 179ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 180ceebc2f3SEric Joyner * --------------------------------- 181ceebc2f3SEric Joyner */ 182ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 183ceebc2f3SEric Joyner dcbcfg->etsrec.tsatable[i] = buf[offset++]; 184ceebc2f3SEric Joyner } 185ceebc2f3SEric Joyner 186ceebc2f3SEric Joyner /** 187ceebc2f3SEric Joyner * i40e_parse_ieee_pfccfg_tlv 188ceebc2f3SEric Joyner * @tlv: IEEE 802.1Qaz PFC CFG TLV 189ceebc2f3SEric Joyner * @dcbcfg: Local store to update PFC CFG data 190ceebc2f3SEric Joyner * 191ceebc2f3SEric Joyner * Parses IEEE 802.1Qaz PFC CFG TLV 192ceebc2f3SEric Joyner **/ 193ceebc2f3SEric Joyner static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv, 194ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 195ceebc2f3SEric Joyner { 196ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 197ceebc2f3SEric Joyner 198ceebc2f3SEric Joyner /* ---------------------------------------- 199ceebc2f3SEric Joyner * |will-|MBC | Re- | PFC | PFC Enable | 200ceebc2f3SEric Joyner * |ing | |served| cap | | 201ceebc2f3SEric Joyner * ----------------------------------------- 202ceebc2f3SEric Joyner * |1bit | 1bit|2 bits|4bits| 1 octet | 203ceebc2f3SEric Joyner */ 204ceebc2f3SEric Joyner dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >> 205ceebc2f3SEric Joyner I40E_IEEE_PFC_WILLING_SHIFT); 206ceebc2f3SEric Joyner dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >> 207ceebc2f3SEric Joyner I40E_IEEE_PFC_MBC_SHIFT); 208ceebc2f3SEric Joyner dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >> 209ceebc2f3SEric Joyner I40E_IEEE_PFC_CAP_SHIFT); 210ceebc2f3SEric Joyner dcbcfg->pfc.pfcenable = buf[1]; 211ceebc2f3SEric Joyner } 212ceebc2f3SEric Joyner 213ceebc2f3SEric Joyner /** 214ceebc2f3SEric Joyner * i40e_parse_ieee_app_tlv 215ceebc2f3SEric Joyner * @tlv: IEEE 802.1Qaz APP TLV 216ceebc2f3SEric Joyner * @dcbcfg: Local store to update APP PRIO data 217ceebc2f3SEric Joyner * 218ceebc2f3SEric Joyner * Parses IEEE 802.1Qaz APP PRIO TLV 219ceebc2f3SEric Joyner **/ 220ceebc2f3SEric Joyner static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv, 221ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 222ceebc2f3SEric Joyner { 223ceebc2f3SEric Joyner u16 typelength; 224ceebc2f3SEric Joyner u16 offset = 0; 225ceebc2f3SEric Joyner u16 length; 226ceebc2f3SEric Joyner int i = 0; 227ceebc2f3SEric Joyner u8 *buf; 228ceebc2f3SEric Joyner 229ceebc2f3SEric Joyner typelength = I40E_NTOHS(tlv->typelength); 230ceebc2f3SEric Joyner length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 231ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 232ceebc2f3SEric Joyner buf = tlv->tlvinfo; 233ceebc2f3SEric Joyner 234ceebc2f3SEric Joyner /* The App priority table starts 5 octets after TLV header */ 235ceebc2f3SEric Joyner length -= (sizeof(tlv->ouisubtype) + 1); 236ceebc2f3SEric Joyner 237ceebc2f3SEric Joyner /* Move offset to App Priority Table */ 238ceebc2f3SEric Joyner offset++; 239ceebc2f3SEric Joyner 240ceebc2f3SEric Joyner /* Application Priority Table (3 octets) 241ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 242ceebc2f3SEric Joyner * ----------------------------------------- 243ceebc2f3SEric Joyner * |Priority|Rsrvd| Sel | Protocol ID | 244ceebc2f3SEric Joyner * ----------------------------------------- 245ceebc2f3SEric Joyner * Bits:|23 21|20 19|18 16|15 0| 246ceebc2f3SEric Joyner * ----------------------------------------- 247ceebc2f3SEric Joyner */ 248ceebc2f3SEric Joyner while (offset < length) { 249ceebc2f3SEric Joyner dcbcfg->app[i].priority = (u8)((buf[offset] & 250ceebc2f3SEric Joyner I40E_IEEE_APP_PRIO_MASK) >> 251ceebc2f3SEric Joyner I40E_IEEE_APP_PRIO_SHIFT); 252ceebc2f3SEric Joyner dcbcfg->app[i].selector = (u8)((buf[offset] & 253ceebc2f3SEric Joyner I40E_IEEE_APP_SEL_MASK) >> 254ceebc2f3SEric Joyner I40E_IEEE_APP_SEL_SHIFT); 255ceebc2f3SEric Joyner dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) | 256ceebc2f3SEric Joyner buf[offset + 2]; 257ceebc2f3SEric Joyner /* Move to next app */ 258ceebc2f3SEric Joyner offset += 3; 259ceebc2f3SEric Joyner i++; 260ceebc2f3SEric Joyner if (i >= I40E_DCBX_MAX_APPS) 261ceebc2f3SEric Joyner break; 262ceebc2f3SEric Joyner } 263ceebc2f3SEric Joyner 264ceebc2f3SEric Joyner dcbcfg->numapps = i; 265ceebc2f3SEric Joyner } 266ceebc2f3SEric Joyner 267ceebc2f3SEric Joyner /** 268ceebc2f3SEric Joyner * i40e_parse_ieee_etsrec_tlv 269ceebc2f3SEric Joyner * @tlv: IEEE 802.1Qaz TLV 270ceebc2f3SEric Joyner * @dcbcfg: Local store to update ETS REC data 271ceebc2f3SEric Joyner * 272ceebc2f3SEric Joyner * Get the TLV subtype and send it to parsing function 273ceebc2f3SEric Joyner * based on the subtype value 274ceebc2f3SEric Joyner **/ 275ceebc2f3SEric Joyner static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv, 276ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 277ceebc2f3SEric Joyner { 278ceebc2f3SEric Joyner u32 ouisubtype; 279ceebc2f3SEric Joyner u8 subtype; 280ceebc2f3SEric Joyner 281ceebc2f3SEric Joyner ouisubtype = I40E_NTOHL(tlv->ouisubtype); 282ceebc2f3SEric Joyner subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> 283ceebc2f3SEric Joyner I40E_LLDP_TLV_SUBTYPE_SHIFT); 284ceebc2f3SEric Joyner switch (subtype) { 285ceebc2f3SEric Joyner case I40E_IEEE_SUBTYPE_ETS_CFG: 286ceebc2f3SEric Joyner i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg); 287ceebc2f3SEric Joyner break; 288ceebc2f3SEric Joyner case I40E_IEEE_SUBTYPE_ETS_REC: 289ceebc2f3SEric Joyner i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg); 290ceebc2f3SEric Joyner break; 291ceebc2f3SEric Joyner case I40E_IEEE_SUBTYPE_PFC_CFG: 292ceebc2f3SEric Joyner i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg); 293ceebc2f3SEric Joyner break; 294ceebc2f3SEric Joyner case I40E_IEEE_SUBTYPE_APP_PRI: 295ceebc2f3SEric Joyner i40e_parse_ieee_app_tlv(tlv, dcbcfg); 296ceebc2f3SEric Joyner break; 297ceebc2f3SEric Joyner default: 298ceebc2f3SEric Joyner break; 299ceebc2f3SEric Joyner } 300ceebc2f3SEric Joyner } 301ceebc2f3SEric Joyner 302ceebc2f3SEric Joyner /** 303ceebc2f3SEric Joyner * i40e_parse_cee_pgcfg_tlv 304ceebc2f3SEric Joyner * @tlv: CEE DCBX PG CFG TLV 305ceebc2f3SEric Joyner * @dcbcfg: Local store to update ETS CFG data 306ceebc2f3SEric Joyner * 307ceebc2f3SEric Joyner * Parses CEE DCBX PG CFG TLV 308ceebc2f3SEric Joyner **/ 309ceebc2f3SEric Joyner static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv, 310ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 311ceebc2f3SEric Joyner { 312ceebc2f3SEric Joyner struct i40e_dcb_ets_config *etscfg; 313ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 314ceebc2f3SEric Joyner u16 offset = 0; 315ceebc2f3SEric Joyner u8 priority; 316ceebc2f3SEric Joyner int i; 317ceebc2f3SEric Joyner 318ceebc2f3SEric Joyner etscfg = &dcbcfg->etscfg; 319ceebc2f3SEric Joyner 320ceebc2f3SEric Joyner if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) 321ceebc2f3SEric Joyner etscfg->willing = 1; 322ceebc2f3SEric Joyner 323ceebc2f3SEric Joyner etscfg->cbs = 0; 324ceebc2f3SEric Joyner /* Priority Group Table (4 octets) 325ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 326ceebc2f3SEric Joyner * ----------------------------------------- 327ceebc2f3SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 328ceebc2f3SEric Joyner * ----------------------------------------- 329ceebc2f3SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 330ceebc2f3SEric Joyner * ----------------------------------------- 331ceebc2f3SEric Joyner */ 332ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 333ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >> 334ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_1_SHIFT); 335ceebc2f3SEric Joyner etscfg->prioritytable[i * 2] = priority; 336ceebc2f3SEric Joyner priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >> 337ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_0_SHIFT); 338ceebc2f3SEric Joyner etscfg->prioritytable[i * 2 + 1] = priority; 339ceebc2f3SEric Joyner offset++; 340ceebc2f3SEric Joyner } 341ceebc2f3SEric Joyner 342ceebc2f3SEric Joyner /* PG Percentage Table (8 octets) 343ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 344ceebc2f3SEric Joyner * --------------------------------- 345ceebc2f3SEric Joyner * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7| 346ceebc2f3SEric Joyner * --------------------------------- 347ceebc2f3SEric Joyner */ 348ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 349ceebc2f3SEric Joyner etscfg->tcbwtable[i] = buf[offset++]; 350ceebc2f3SEric Joyner 351ceebc2f3SEric Joyner /* Number of TCs supported (1 octet) */ 352ceebc2f3SEric Joyner etscfg->maxtcs = buf[offset]; 353ceebc2f3SEric Joyner } 354ceebc2f3SEric Joyner 355ceebc2f3SEric Joyner /** 356ceebc2f3SEric Joyner * i40e_parse_cee_pfccfg_tlv 357ceebc2f3SEric Joyner * @tlv: CEE DCBX PFC CFG TLV 358ceebc2f3SEric Joyner * @dcbcfg: Local store to update PFC CFG data 359ceebc2f3SEric Joyner * 360ceebc2f3SEric Joyner * Parses CEE DCBX PFC CFG TLV 361ceebc2f3SEric Joyner **/ 362ceebc2f3SEric Joyner static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv, 363ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 364ceebc2f3SEric Joyner { 365ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 366ceebc2f3SEric Joyner 367ceebc2f3SEric Joyner if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) 368ceebc2f3SEric Joyner dcbcfg->pfc.willing = 1; 369ceebc2f3SEric Joyner 370ceebc2f3SEric Joyner /* ------------------------ 371ceebc2f3SEric Joyner * | PFC Enable | PFC TCs | 372ceebc2f3SEric Joyner * ------------------------ 373ceebc2f3SEric Joyner * | 1 octet | 1 octet | 374ceebc2f3SEric Joyner */ 375ceebc2f3SEric Joyner dcbcfg->pfc.pfcenable = buf[0]; 376ceebc2f3SEric Joyner dcbcfg->pfc.pfccap = buf[1]; 377ceebc2f3SEric Joyner } 378ceebc2f3SEric Joyner 379ceebc2f3SEric Joyner /** 380ceebc2f3SEric Joyner * i40e_parse_cee_app_tlv 381ceebc2f3SEric Joyner * @tlv: CEE DCBX APP TLV 382ceebc2f3SEric Joyner * @dcbcfg: Local store to update APP PRIO data 383ceebc2f3SEric Joyner * 384ceebc2f3SEric Joyner * Parses CEE DCBX APP PRIO TLV 385ceebc2f3SEric Joyner **/ 386ceebc2f3SEric Joyner static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, 387ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 388ceebc2f3SEric Joyner { 389ceebc2f3SEric Joyner u16 length, typelength, offset = 0; 390ceebc2f3SEric Joyner struct i40e_cee_app_prio *app; 391ceebc2f3SEric Joyner u8 i; 392ceebc2f3SEric Joyner 393ceebc2f3SEric Joyner typelength = I40E_NTOHS(tlv->hdr.typelen); 394ceebc2f3SEric Joyner length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 395ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 396ceebc2f3SEric Joyner 397ceebc2f3SEric Joyner dcbcfg->numapps = length / sizeof(*app); 398ceebc2f3SEric Joyner if (!dcbcfg->numapps) 399ceebc2f3SEric Joyner return; 400ceebc2f3SEric Joyner if (dcbcfg->numapps > I40E_DCBX_MAX_APPS) 401ceebc2f3SEric Joyner dcbcfg->numapps = I40E_DCBX_MAX_APPS; 402ceebc2f3SEric Joyner 403ceebc2f3SEric Joyner for (i = 0; i < dcbcfg->numapps; i++) { 404ceebc2f3SEric Joyner u8 up, selector; 405ceebc2f3SEric Joyner 406ceebc2f3SEric Joyner app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset); 407ceebc2f3SEric Joyner for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) { 408ceebc2f3SEric Joyner if (app->prio_map & BIT(up)) 409ceebc2f3SEric Joyner break; 410ceebc2f3SEric Joyner } 411ceebc2f3SEric Joyner dcbcfg->app[i].priority = up; 412ceebc2f3SEric Joyner 413ceebc2f3SEric Joyner /* Get Selector from lower 2 bits, and convert to IEEE */ 414ceebc2f3SEric Joyner selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK); 415ceebc2f3SEric Joyner switch (selector) { 416ceebc2f3SEric Joyner case I40E_CEE_APP_SEL_ETHTYPE: 417ceebc2f3SEric Joyner dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 418ceebc2f3SEric Joyner break; 419ceebc2f3SEric Joyner case I40E_CEE_APP_SEL_TCPIP: 420ceebc2f3SEric Joyner dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; 421ceebc2f3SEric Joyner break; 422ceebc2f3SEric Joyner default: 423ceebc2f3SEric Joyner /* Keep selector as it is for unknown types */ 424ceebc2f3SEric Joyner dcbcfg->app[i].selector = selector; 425ceebc2f3SEric Joyner } 426ceebc2f3SEric Joyner 427ceebc2f3SEric Joyner dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol); 428ceebc2f3SEric Joyner /* Move to next app */ 429ceebc2f3SEric Joyner offset += sizeof(*app); 430ceebc2f3SEric Joyner } 431ceebc2f3SEric Joyner } 432ceebc2f3SEric Joyner 433ceebc2f3SEric Joyner /** 434ceebc2f3SEric Joyner * i40e_parse_cee_tlv 435ceebc2f3SEric Joyner * @tlv: CEE DCBX TLV 436ceebc2f3SEric Joyner * @dcbcfg: Local store to update DCBX config data 437ceebc2f3SEric Joyner * 438ceebc2f3SEric Joyner * Get the TLV subtype and send it to parsing function 439ceebc2f3SEric Joyner * based on the subtype value 440ceebc2f3SEric Joyner **/ 441ceebc2f3SEric Joyner static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv, 442ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 443ceebc2f3SEric Joyner { 444ceebc2f3SEric Joyner u16 len, tlvlen, sublen, typelength; 445ceebc2f3SEric Joyner struct i40e_cee_feat_tlv *sub_tlv; 446ceebc2f3SEric Joyner u8 subtype, feat_tlv_count = 0; 447ceebc2f3SEric Joyner u32 ouisubtype; 448ceebc2f3SEric Joyner 449ceebc2f3SEric Joyner ouisubtype = I40E_NTOHL(tlv->ouisubtype); 450ceebc2f3SEric Joyner subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> 451ceebc2f3SEric Joyner I40E_LLDP_TLV_SUBTYPE_SHIFT); 452ceebc2f3SEric Joyner /* Return if not CEE DCBX */ 453ceebc2f3SEric Joyner if (subtype != I40E_CEE_DCBX_TYPE) 454ceebc2f3SEric Joyner return; 455ceebc2f3SEric Joyner 456ceebc2f3SEric Joyner typelength = I40E_NTOHS(tlv->typelength); 457ceebc2f3SEric Joyner tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 458ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 459ceebc2f3SEric Joyner len = sizeof(tlv->typelength) + sizeof(ouisubtype) + 460ceebc2f3SEric Joyner sizeof(struct i40e_cee_ctrl_tlv); 461ceebc2f3SEric Joyner /* Return if no CEE DCBX Feature TLVs */ 462ceebc2f3SEric Joyner if (tlvlen <= len) 463ceebc2f3SEric Joyner return; 464ceebc2f3SEric Joyner 465ceebc2f3SEric Joyner sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len); 466ceebc2f3SEric Joyner while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) { 467ceebc2f3SEric Joyner typelength = I40E_NTOHS(sub_tlv->hdr.typelen); 468ceebc2f3SEric Joyner sublen = (u16)((typelength & 469ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_MASK) >> 470ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 471ceebc2f3SEric Joyner subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> 472ceebc2f3SEric Joyner I40E_LLDP_TLV_TYPE_SHIFT); 473ceebc2f3SEric Joyner switch (subtype) { 474ceebc2f3SEric Joyner case I40E_CEE_SUBTYPE_PG_CFG: 475ceebc2f3SEric Joyner i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); 476ceebc2f3SEric Joyner break; 477ceebc2f3SEric Joyner case I40E_CEE_SUBTYPE_PFC_CFG: 478ceebc2f3SEric Joyner i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); 479ceebc2f3SEric Joyner break; 480ceebc2f3SEric Joyner case I40E_CEE_SUBTYPE_APP_PRI: 481ceebc2f3SEric Joyner i40e_parse_cee_app_tlv(sub_tlv, dcbcfg); 482ceebc2f3SEric Joyner break; 483ceebc2f3SEric Joyner default: 484ceebc2f3SEric Joyner return; /* Invalid Sub-type return */ 485ceebc2f3SEric Joyner } 486ceebc2f3SEric Joyner feat_tlv_count++; 487ceebc2f3SEric Joyner /* Move to next sub TLV */ 488ceebc2f3SEric Joyner sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv + 489ceebc2f3SEric Joyner sizeof(sub_tlv->hdr.typelen) + 490ceebc2f3SEric Joyner sublen); 491ceebc2f3SEric Joyner } 492ceebc2f3SEric Joyner } 493ceebc2f3SEric Joyner 494ceebc2f3SEric Joyner /** 495ceebc2f3SEric Joyner * i40e_parse_org_tlv 496ceebc2f3SEric Joyner * @tlv: Organization specific TLV 497ceebc2f3SEric Joyner * @dcbcfg: Local store to update ETS REC data 498ceebc2f3SEric Joyner * 499ceebc2f3SEric Joyner * Currently only IEEE 802.1Qaz TLV is supported, all others 500ceebc2f3SEric Joyner * will be returned 501ceebc2f3SEric Joyner **/ 502ceebc2f3SEric Joyner static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv, 503ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 504ceebc2f3SEric Joyner { 505ceebc2f3SEric Joyner u32 ouisubtype; 506ceebc2f3SEric Joyner u32 oui; 507ceebc2f3SEric Joyner 508ceebc2f3SEric Joyner ouisubtype = I40E_NTOHL(tlv->ouisubtype); 509ceebc2f3SEric Joyner oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >> 510ceebc2f3SEric Joyner I40E_LLDP_TLV_OUI_SHIFT); 511ceebc2f3SEric Joyner switch (oui) { 512ceebc2f3SEric Joyner case I40E_IEEE_8021QAZ_OUI: 513ceebc2f3SEric Joyner i40e_parse_ieee_tlv(tlv, dcbcfg); 514ceebc2f3SEric Joyner break; 515ceebc2f3SEric Joyner case I40E_CEE_DCBX_OUI: 516ceebc2f3SEric Joyner i40e_parse_cee_tlv(tlv, dcbcfg); 517ceebc2f3SEric Joyner break; 518ceebc2f3SEric Joyner default: 519ceebc2f3SEric Joyner break; 520ceebc2f3SEric Joyner } 521ceebc2f3SEric Joyner } 522ceebc2f3SEric Joyner 523ceebc2f3SEric Joyner /** 524ceebc2f3SEric Joyner * i40e_lldp_to_dcb_config 525ceebc2f3SEric Joyner * @lldpmib: LLDPDU to be parsed 526ceebc2f3SEric Joyner * @dcbcfg: store for LLDPDU data 527ceebc2f3SEric Joyner * 528ceebc2f3SEric Joyner * Parse DCB configuration from the LLDPDU 529ceebc2f3SEric Joyner **/ 530ceebc2f3SEric Joyner enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib, 531ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 532ceebc2f3SEric Joyner { 533ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 534ceebc2f3SEric Joyner struct i40e_lldp_org_tlv *tlv; 535ceebc2f3SEric Joyner u16 type; 536ceebc2f3SEric Joyner u16 length; 537ceebc2f3SEric Joyner u16 typelength; 538ceebc2f3SEric Joyner u16 offset = 0; 539ceebc2f3SEric Joyner 540ceebc2f3SEric Joyner if (!lldpmib || !dcbcfg) 541ceebc2f3SEric Joyner return I40E_ERR_PARAM; 542ceebc2f3SEric Joyner 543ceebc2f3SEric Joyner /* set to the start of LLDPDU */ 544ceebc2f3SEric Joyner lldpmib += I40E_LLDP_MIB_HLEN; 545ceebc2f3SEric Joyner tlv = (struct i40e_lldp_org_tlv *)lldpmib; 546ceebc2f3SEric Joyner while (1) { 547ceebc2f3SEric Joyner typelength = I40E_NTOHS(tlv->typelength); 548ceebc2f3SEric Joyner type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> 549ceebc2f3SEric Joyner I40E_LLDP_TLV_TYPE_SHIFT); 550ceebc2f3SEric Joyner length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 551ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 552ceebc2f3SEric Joyner offset += sizeof(typelength) + length; 553ceebc2f3SEric Joyner 554ceebc2f3SEric Joyner /* END TLV or beyond LLDPDU size */ 555ceebc2f3SEric Joyner if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE)) 556ceebc2f3SEric Joyner break; 557ceebc2f3SEric Joyner 558ceebc2f3SEric Joyner switch (type) { 559ceebc2f3SEric Joyner case I40E_TLV_TYPE_ORG: 560ceebc2f3SEric Joyner i40e_parse_org_tlv(tlv, dcbcfg); 561ceebc2f3SEric Joyner break; 562ceebc2f3SEric Joyner default: 563ceebc2f3SEric Joyner break; 564ceebc2f3SEric Joyner } 565ceebc2f3SEric Joyner 566ceebc2f3SEric Joyner /* Move to next TLV */ 567ceebc2f3SEric Joyner tlv = (struct i40e_lldp_org_tlv *)((char *)tlv + 568ceebc2f3SEric Joyner sizeof(tlv->typelength) + 569ceebc2f3SEric Joyner length); 570ceebc2f3SEric Joyner } 571ceebc2f3SEric Joyner 572ceebc2f3SEric Joyner return ret; 573ceebc2f3SEric Joyner } 574ceebc2f3SEric Joyner 575ceebc2f3SEric Joyner /** 576ceebc2f3SEric Joyner * i40e_aq_get_dcb_config 577ceebc2f3SEric Joyner * @hw: pointer to the hw struct 578ceebc2f3SEric Joyner * @mib_type: mib type for the query 579ceebc2f3SEric Joyner * @bridgetype: bridge type for the query (remote) 580ceebc2f3SEric Joyner * @dcbcfg: store for LLDPDU data 581ceebc2f3SEric Joyner * 582ceebc2f3SEric Joyner * Query DCB configuration from the Firmware 583ceebc2f3SEric Joyner **/ 584ceebc2f3SEric Joyner enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type, 585ceebc2f3SEric Joyner u8 bridgetype, 586ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 587ceebc2f3SEric Joyner { 588ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 589ceebc2f3SEric Joyner struct i40e_virt_mem mem; 590ceebc2f3SEric Joyner u8 *lldpmib; 591ceebc2f3SEric Joyner 592ceebc2f3SEric Joyner /* Allocate the LLDPDU */ 593ceebc2f3SEric Joyner ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 594ceebc2f3SEric Joyner if (ret) 595ceebc2f3SEric Joyner return ret; 596ceebc2f3SEric Joyner 597ceebc2f3SEric Joyner lldpmib = (u8 *)mem.va; 598ceebc2f3SEric Joyner ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type, 599ceebc2f3SEric Joyner (void *)lldpmib, I40E_LLDPDU_SIZE, 600ceebc2f3SEric Joyner NULL, NULL, NULL); 601ceebc2f3SEric Joyner if (ret) 602ceebc2f3SEric Joyner goto free_mem; 603ceebc2f3SEric Joyner 604ceebc2f3SEric Joyner /* Parse LLDP MIB to get dcb configuration */ 605ceebc2f3SEric Joyner ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg); 606ceebc2f3SEric Joyner 607ceebc2f3SEric Joyner free_mem: 608ceebc2f3SEric Joyner i40e_free_virt_mem(hw, &mem); 609ceebc2f3SEric Joyner return ret; 610ceebc2f3SEric Joyner } 611ceebc2f3SEric Joyner 612ceebc2f3SEric Joyner /** 613ceebc2f3SEric Joyner * i40e_cee_to_dcb_v1_config 614ceebc2f3SEric Joyner * @cee_cfg: pointer to CEE v1 response configuration struct 615ceebc2f3SEric Joyner * @dcbcfg: DCB configuration struct 616ceebc2f3SEric Joyner * 617ceebc2f3SEric Joyner * Convert CEE v1 configuration from firmware to DCB configuration 618ceebc2f3SEric Joyner **/ 619ceebc2f3SEric Joyner static void i40e_cee_to_dcb_v1_config( 620ceebc2f3SEric Joyner struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg, 621ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 622ceebc2f3SEric Joyner { 623ceebc2f3SEric Joyner u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status); 624ceebc2f3SEric Joyner u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio); 625ceebc2f3SEric Joyner u8 i, tc, err; 626ceebc2f3SEric Joyner 627ceebc2f3SEric Joyner /* CEE PG data to ETS config */ 628ceebc2f3SEric Joyner dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 629ceebc2f3SEric Joyner 630ceebc2f3SEric Joyner /* Note that the FW creates the oper_prio_tc nibbles reversed 631ceebc2f3SEric Joyner * from those in the CEE Priority Group sub-TLV. 632ceebc2f3SEric Joyner */ 633ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 634ceebc2f3SEric Joyner tc = (u8)((cee_cfg->oper_prio_tc[i] & 635ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_0_MASK) >> 636ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_0_SHIFT); 637ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i*2] = tc; 638ceebc2f3SEric Joyner tc = (u8)((cee_cfg->oper_prio_tc[i] & 639ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_1_MASK) >> 640ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_1_SHIFT); 641ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; 642ceebc2f3SEric Joyner } 643ceebc2f3SEric Joyner 644ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 645ceebc2f3SEric Joyner dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 646ceebc2f3SEric Joyner 647ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 648ceebc2f3SEric Joyner if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { 649ceebc2f3SEric Joyner /* Map it to next empty TC */ 650ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i] = 651ceebc2f3SEric Joyner cee_cfg->oper_num_tc - 1; 652ceebc2f3SEric Joyner dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; 653ceebc2f3SEric Joyner } else { 654ceebc2f3SEric Joyner dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; 655ceebc2f3SEric Joyner } 656ceebc2f3SEric Joyner } 657ceebc2f3SEric Joyner 658ceebc2f3SEric Joyner /* CEE PFC data to ETS config */ 659ceebc2f3SEric Joyner dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; 660ceebc2f3SEric Joyner dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 661ceebc2f3SEric Joyner 662ceebc2f3SEric Joyner status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> 663ceebc2f3SEric Joyner I40E_AQC_CEE_APP_STATUS_SHIFT; 664ceebc2f3SEric Joyner err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 665ceebc2f3SEric Joyner /* Add APPs if Error is False */ 666ceebc2f3SEric Joyner if (!err) { 667ceebc2f3SEric Joyner /* CEE operating configuration supports FCoE/iSCSI/FIP only */ 668ceebc2f3SEric Joyner dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; 669ceebc2f3SEric Joyner 670ceebc2f3SEric Joyner /* FCoE APP */ 671ceebc2f3SEric Joyner dcbcfg->app[0].priority = 672ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> 673ceebc2f3SEric Joyner I40E_AQC_CEE_APP_FCOE_SHIFT; 674ceebc2f3SEric Joyner dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; 675ceebc2f3SEric Joyner dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; 676ceebc2f3SEric Joyner 677ceebc2f3SEric Joyner /* iSCSI APP */ 678ceebc2f3SEric Joyner dcbcfg->app[1].priority = 679ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> 680ceebc2f3SEric Joyner I40E_AQC_CEE_APP_ISCSI_SHIFT; 681ceebc2f3SEric Joyner dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; 682ceebc2f3SEric Joyner dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; 683ceebc2f3SEric Joyner 684ceebc2f3SEric Joyner /* FIP APP */ 685ceebc2f3SEric Joyner dcbcfg->app[2].priority = 686ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> 687ceebc2f3SEric Joyner I40E_AQC_CEE_APP_FIP_SHIFT; 688ceebc2f3SEric Joyner dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; 689ceebc2f3SEric Joyner dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; 690ceebc2f3SEric Joyner } 691ceebc2f3SEric Joyner } 692ceebc2f3SEric Joyner 693ceebc2f3SEric Joyner /** 694ceebc2f3SEric Joyner * i40e_cee_to_dcb_config 695ceebc2f3SEric Joyner * @cee_cfg: pointer to CEE configuration struct 696ceebc2f3SEric Joyner * @dcbcfg: DCB configuration struct 697ceebc2f3SEric Joyner * 698ceebc2f3SEric Joyner * Convert CEE configuration from firmware to DCB configuration 699ceebc2f3SEric Joyner **/ 700ceebc2f3SEric Joyner static void i40e_cee_to_dcb_config( 701ceebc2f3SEric Joyner struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg, 702ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 703ceebc2f3SEric Joyner { 704ceebc2f3SEric Joyner u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status); 705ceebc2f3SEric Joyner u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio); 706ceebc2f3SEric Joyner u8 i, tc, err, sync, oper; 707ceebc2f3SEric Joyner 708ceebc2f3SEric Joyner /* CEE PG data to ETS config */ 709ceebc2f3SEric Joyner dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 710ceebc2f3SEric Joyner 711ceebc2f3SEric Joyner /* Note that the FW creates the oper_prio_tc nibbles reversed 712ceebc2f3SEric Joyner * from those in the CEE Priority Group sub-TLV. 713ceebc2f3SEric Joyner */ 714ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 715ceebc2f3SEric Joyner tc = (u8)((cee_cfg->oper_prio_tc[i] & 716ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_0_MASK) >> 717ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_0_SHIFT); 718ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i*2] = tc; 719ceebc2f3SEric Joyner tc = (u8)((cee_cfg->oper_prio_tc[i] & 720ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_1_MASK) >> 721ceebc2f3SEric Joyner I40E_CEE_PGID_PRIO_1_SHIFT); 722ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; 723ceebc2f3SEric Joyner } 724ceebc2f3SEric Joyner 725ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 726ceebc2f3SEric Joyner dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 727ceebc2f3SEric Joyner 728ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 729ceebc2f3SEric Joyner if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { 730ceebc2f3SEric Joyner /* Map it to next empty TC */ 731ceebc2f3SEric Joyner dcbcfg->etscfg.prioritytable[i] = 732ceebc2f3SEric Joyner cee_cfg->oper_num_tc - 1; 733ceebc2f3SEric Joyner dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; 734ceebc2f3SEric Joyner } else { 735ceebc2f3SEric Joyner dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; 736ceebc2f3SEric Joyner } 737ceebc2f3SEric Joyner } 738ceebc2f3SEric Joyner 739ceebc2f3SEric Joyner /* CEE PFC data to ETS config */ 740ceebc2f3SEric Joyner dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; 741ceebc2f3SEric Joyner dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 742ceebc2f3SEric Joyner 743ceebc2f3SEric Joyner i = 0; 744ceebc2f3SEric Joyner status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >> 745ceebc2f3SEric Joyner I40E_AQC_CEE_FCOE_STATUS_SHIFT; 746ceebc2f3SEric Joyner err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 747ceebc2f3SEric Joyner sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 748ceebc2f3SEric Joyner oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 749ceebc2f3SEric Joyner /* Add FCoE APP if Error is False and Oper/Sync is True */ 750ceebc2f3SEric Joyner if (!err && sync && oper) { 751ceebc2f3SEric Joyner /* FCoE APP */ 752ceebc2f3SEric Joyner dcbcfg->app[i].priority = 753ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> 754ceebc2f3SEric Joyner I40E_AQC_CEE_APP_FCOE_SHIFT; 755ceebc2f3SEric Joyner dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 756ceebc2f3SEric Joyner dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE; 757ceebc2f3SEric Joyner i++; 758ceebc2f3SEric Joyner } 759ceebc2f3SEric Joyner 760ceebc2f3SEric Joyner status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >> 761ceebc2f3SEric Joyner I40E_AQC_CEE_ISCSI_STATUS_SHIFT; 762ceebc2f3SEric Joyner err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 763ceebc2f3SEric Joyner sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 764ceebc2f3SEric Joyner oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 765ceebc2f3SEric Joyner /* Add iSCSI APP if Error is False and Oper/Sync is True */ 766ceebc2f3SEric Joyner if (!err && sync && oper) { 767ceebc2f3SEric Joyner /* iSCSI APP */ 768ceebc2f3SEric Joyner dcbcfg->app[i].priority = 769ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> 770ceebc2f3SEric Joyner I40E_AQC_CEE_APP_ISCSI_SHIFT; 771ceebc2f3SEric Joyner dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; 772ceebc2f3SEric Joyner dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI; 773ceebc2f3SEric Joyner i++; 774ceebc2f3SEric Joyner } 775ceebc2f3SEric Joyner 776ceebc2f3SEric Joyner status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >> 777ceebc2f3SEric Joyner I40E_AQC_CEE_FIP_STATUS_SHIFT; 778ceebc2f3SEric Joyner err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 779ceebc2f3SEric Joyner sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 780ceebc2f3SEric Joyner oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 781ceebc2f3SEric Joyner /* Add FIP APP if Error is False and Oper/Sync is True */ 782ceebc2f3SEric Joyner if (!err && sync && oper) { 783ceebc2f3SEric Joyner /* FIP APP */ 784ceebc2f3SEric Joyner dcbcfg->app[i].priority = 785ceebc2f3SEric Joyner (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> 786ceebc2f3SEric Joyner I40E_AQC_CEE_APP_FIP_SHIFT; 787ceebc2f3SEric Joyner dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 788ceebc2f3SEric Joyner dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP; 789ceebc2f3SEric Joyner i++; 790ceebc2f3SEric Joyner } 791ceebc2f3SEric Joyner dcbcfg->numapps = i; 792ceebc2f3SEric Joyner } 793ceebc2f3SEric Joyner 794ceebc2f3SEric Joyner /** 795ceebc2f3SEric Joyner * i40e_get_ieee_dcb_config 796ceebc2f3SEric Joyner * @hw: pointer to the hw struct 797ceebc2f3SEric Joyner * 798ceebc2f3SEric Joyner * Get IEEE mode DCB configuration from the Firmware 799ceebc2f3SEric Joyner **/ 800ceebc2f3SEric Joyner static enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw) 801ceebc2f3SEric Joyner { 802ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 803ceebc2f3SEric Joyner 804ceebc2f3SEric Joyner /* IEEE mode */ 805ceebc2f3SEric Joyner hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; 806ceebc2f3SEric Joyner /* Get Local DCB Config */ 807ceebc2f3SEric Joyner ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, 808ceebc2f3SEric Joyner &hw->local_dcbx_config); 809ceebc2f3SEric Joyner if (ret) 810ceebc2f3SEric Joyner goto out; 811ceebc2f3SEric Joyner 812ceebc2f3SEric Joyner /* Get Remote DCB Config */ 813ceebc2f3SEric Joyner ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, 814ceebc2f3SEric Joyner I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, 815ceebc2f3SEric Joyner &hw->remote_dcbx_config); 816ceebc2f3SEric Joyner /* Don't treat ENOENT as an error for Remote MIBs */ 817ceebc2f3SEric Joyner if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 818ceebc2f3SEric Joyner ret = I40E_SUCCESS; 819ceebc2f3SEric Joyner 820ceebc2f3SEric Joyner out: 821ceebc2f3SEric Joyner return ret; 822ceebc2f3SEric Joyner } 823ceebc2f3SEric Joyner 824ceebc2f3SEric Joyner /** 825ceebc2f3SEric Joyner * i40e_get_dcb_config 826ceebc2f3SEric Joyner * @hw: pointer to the hw struct 827ceebc2f3SEric Joyner * 828ceebc2f3SEric Joyner * Get DCB configuration from the Firmware 829ceebc2f3SEric Joyner **/ 830ceebc2f3SEric Joyner enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw) 831ceebc2f3SEric Joyner { 832ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 833ceebc2f3SEric Joyner struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; 834ceebc2f3SEric Joyner struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; 835ceebc2f3SEric Joyner 836ceebc2f3SEric Joyner /* If Firmware version < v4.33 on X710/XL710, IEEE only */ 837ceebc2f3SEric Joyner if ((hw->mac.type == I40E_MAC_XL710) && 838ceebc2f3SEric Joyner (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || 839ceebc2f3SEric Joyner (hw->aq.fw_maj_ver < 4))) 840ceebc2f3SEric Joyner return i40e_get_ieee_dcb_config(hw); 841ceebc2f3SEric Joyner 842ceebc2f3SEric Joyner /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */ 843ceebc2f3SEric Joyner if ((hw->mac.type == I40E_MAC_XL710) && 844ceebc2f3SEric Joyner ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) { 845ceebc2f3SEric Joyner ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, 846ceebc2f3SEric Joyner sizeof(cee_v1_cfg), NULL); 847ceebc2f3SEric Joyner if (ret == I40E_SUCCESS) { 848ceebc2f3SEric Joyner /* CEE mode */ 849ceebc2f3SEric Joyner hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; 850ceebc2f3SEric Joyner hw->local_dcbx_config.tlv_status = 851ceebc2f3SEric Joyner LE16_TO_CPU(cee_v1_cfg.tlv_status); 852ceebc2f3SEric Joyner i40e_cee_to_dcb_v1_config(&cee_v1_cfg, 853ceebc2f3SEric Joyner &hw->local_dcbx_config); 854ceebc2f3SEric Joyner } 855ceebc2f3SEric Joyner } else { 856ceebc2f3SEric Joyner ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg, 857ceebc2f3SEric Joyner sizeof(cee_cfg), NULL); 858ceebc2f3SEric Joyner if (ret == I40E_SUCCESS) { 859ceebc2f3SEric Joyner /* CEE mode */ 860ceebc2f3SEric Joyner hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; 861ceebc2f3SEric Joyner hw->local_dcbx_config.tlv_status = 862ceebc2f3SEric Joyner LE32_TO_CPU(cee_cfg.tlv_status); 863ceebc2f3SEric Joyner i40e_cee_to_dcb_config(&cee_cfg, 864ceebc2f3SEric Joyner &hw->local_dcbx_config); 865ceebc2f3SEric Joyner } 866ceebc2f3SEric Joyner } 867ceebc2f3SEric Joyner 868ceebc2f3SEric Joyner /* CEE mode not enabled try querying IEEE data */ 869ceebc2f3SEric Joyner if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 870ceebc2f3SEric Joyner return i40e_get_ieee_dcb_config(hw); 871ceebc2f3SEric Joyner 872ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 873ceebc2f3SEric Joyner goto out; 874ceebc2f3SEric Joyner 875ceebc2f3SEric Joyner /* Get CEE DCB Desired Config */ 876ceebc2f3SEric Joyner ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, 877ceebc2f3SEric Joyner &hw->desired_dcbx_config); 878ceebc2f3SEric Joyner if (ret) 879ceebc2f3SEric Joyner goto out; 880ceebc2f3SEric Joyner 881ceebc2f3SEric Joyner /* Get Remote DCB Config */ 882ceebc2f3SEric Joyner ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, 883ceebc2f3SEric Joyner I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, 884ceebc2f3SEric Joyner &hw->remote_dcbx_config); 885ceebc2f3SEric Joyner /* Don't treat ENOENT as an error for Remote MIBs */ 886ceebc2f3SEric Joyner if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 887ceebc2f3SEric Joyner ret = I40E_SUCCESS; 888ceebc2f3SEric Joyner 889ceebc2f3SEric Joyner out: 890ceebc2f3SEric Joyner return ret; 891ceebc2f3SEric Joyner } 892ceebc2f3SEric Joyner 893ceebc2f3SEric Joyner /** 894ceebc2f3SEric Joyner * i40e_init_dcb 895ceebc2f3SEric Joyner * @hw: pointer to the hw struct 896*b4a7ce06SEric Joyner * @enable_mib_change: enable mib change event 897ceebc2f3SEric Joyner * 898ceebc2f3SEric Joyner * Update DCB configuration from the Firmware 899ceebc2f3SEric Joyner **/ 900*b4a7ce06SEric Joyner enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) 901ceebc2f3SEric Joyner { 902ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 903ceebc2f3SEric Joyner struct i40e_lldp_variables lldp_cfg; 904ceebc2f3SEric Joyner u8 adminstatus = 0; 905ceebc2f3SEric Joyner 906ceebc2f3SEric Joyner if (!hw->func_caps.dcb) 907*b4a7ce06SEric Joyner return I40E_NOT_SUPPORTED; 908ceebc2f3SEric Joyner 909ceebc2f3SEric Joyner /* Read LLDP NVM area */ 910*b4a7ce06SEric Joyner if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) { 911*b4a7ce06SEric Joyner u8 offset = 0; 912*b4a7ce06SEric Joyner 913*b4a7ce06SEric Joyner if (hw->mac.type == I40E_MAC_XL710) 914*b4a7ce06SEric Joyner offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET; 915*b4a7ce06SEric Joyner else if (hw->mac.type == I40E_MAC_X722) 916*b4a7ce06SEric Joyner offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET; 917*b4a7ce06SEric Joyner else 918*b4a7ce06SEric Joyner return I40E_NOT_SUPPORTED; 919*b4a7ce06SEric Joyner 920*b4a7ce06SEric Joyner ret = i40e_read_nvm_module_data(hw, 921*b4a7ce06SEric Joyner I40E_SR_EMP_SR_SETTINGS_PTR, 922*b4a7ce06SEric Joyner offset, 923*b4a7ce06SEric Joyner I40E_LLDP_CURRENT_STATUS_OFFSET, 924*b4a7ce06SEric Joyner I40E_LLDP_CURRENT_STATUS_SIZE, 925*b4a7ce06SEric Joyner &lldp_cfg.adminstatus); 926*b4a7ce06SEric Joyner } else { 927ceebc2f3SEric Joyner ret = i40e_read_lldp_cfg(hw, &lldp_cfg); 928*b4a7ce06SEric Joyner } 929ceebc2f3SEric Joyner if (ret) 930*b4a7ce06SEric Joyner return I40E_ERR_NOT_READY; 931ceebc2f3SEric Joyner 932ceebc2f3SEric Joyner /* Get the LLDP AdminStatus for the current port */ 933ceebc2f3SEric Joyner adminstatus = lldp_cfg.adminstatus >> (hw->port * 4); 934ceebc2f3SEric Joyner adminstatus &= 0xF; 935ceebc2f3SEric Joyner 936ceebc2f3SEric Joyner /* LLDP agent disabled */ 937ceebc2f3SEric Joyner if (!adminstatus) { 938ceebc2f3SEric Joyner hw->dcbx_status = I40E_DCBX_STATUS_DISABLED; 939*b4a7ce06SEric Joyner return I40E_ERR_NOT_READY; 940ceebc2f3SEric Joyner } 941ceebc2f3SEric Joyner 942ceebc2f3SEric Joyner /* Get DCBX status */ 943ceebc2f3SEric Joyner ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); 944ceebc2f3SEric Joyner if (ret) 945ceebc2f3SEric Joyner return ret; 946ceebc2f3SEric Joyner 947ceebc2f3SEric Joyner /* Check the DCBX Status */ 948*b4a7ce06SEric Joyner if (hw->dcbx_status == I40E_DCBX_STATUS_DONE || 949*b4a7ce06SEric Joyner hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) { 950ceebc2f3SEric Joyner /* Get current DCBX configuration */ 951ceebc2f3SEric Joyner ret = i40e_get_dcb_config(hw); 952ceebc2f3SEric Joyner if (ret) 953ceebc2f3SEric Joyner return ret; 954*b4a7ce06SEric Joyner } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) { 955*b4a7ce06SEric Joyner return I40E_ERR_NOT_READY; 956ceebc2f3SEric Joyner } 957ceebc2f3SEric Joyner 958ceebc2f3SEric Joyner /* Configure the LLDP MIB change event */ 959*b4a7ce06SEric Joyner if (enable_mib_change) 960ceebc2f3SEric Joyner ret = i40e_aq_cfg_lldp_mib_change_event(hw, TRUE, NULL); 961ceebc2f3SEric Joyner 962ceebc2f3SEric Joyner return ret; 963ceebc2f3SEric Joyner } 964ceebc2f3SEric Joyner 965ceebc2f3SEric Joyner /** 966*b4a7ce06SEric Joyner * i40e_get_fw_lldp_status 967*b4a7ce06SEric Joyner * @hw: pointer to the hw struct 968*b4a7ce06SEric Joyner * @lldp_status: pointer to the status enum 969*b4a7ce06SEric Joyner * 970*b4a7ce06SEric Joyner * Get status of FW Link Layer Discovery Protocol (LLDP) Agent. 971*b4a7ce06SEric Joyner * Status of agent is reported via @lldp_status parameter. 972*b4a7ce06SEric Joyner **/ 973*b4a7ce06SEric Joyner enum i40e_status_code 974*b4a7ce06SEric Joyner i40e_get_fw_lldp_status(struct i40e_hw *hw, 975*b4a7ce06SEric Joyner enum i40e_get_fw_lldp_status_resp *lldp_status) 976*b4a7ce06SEric Joyner { 977*b4a7ce06SEric Joyner enum i40e_status_code ret; 978*b4a7ce06SEric Joyner struct i40e_virt_mem mem; 979*b4a7ce06SEric Joyner u8 *lldpmib; 980*b4a7ce06SEric Joyner 981*b4a7ce06SEric Joyner if (!lldp_status) 982*b4a7ce06SEric Joyner return I40E_ERR_PARAM; 983*b4a7ce06SEric Joyner 984*b4a7ce06SEric Joyner /* Allocate buffer for the LLDPDU */ 985*b4a7ce06SEric Joyner ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 986*b4a7ce06SEric Joyner if (ret) 987*b4a7ce06SEric Joyner return ret; 988*b4a7ce06SEric Joyner 989*b4a7ce06SEric Joyner lldpmib = (u8 *)mem.va; 990*b4a7ce06SEric Joyner ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib, 991*b4a7ce06SEric Joyner I40E_LLDPDU_SIZE, NULL, NULL, NULL); 992*b4a7ce06SEric Joyner 993*b4a7ce06SEric Joyner if (ret == I40E_SUCCESS) { 994*b4a7ce06SEric Joyner *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED; 995*b4a7ce06SEric Joyner } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) { 996*b4a7ce06SEric Joyner /* MIB is not available yet but the agent is running */ 997*b4a7ce06SEric Joyner *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED; 998*b4a7ce06SEric Joyner ret = I40E_SUCCESS; 999*b4a7ce06SEric Joyner } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) { 1000*b4a7ce06SEric Joyner *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED; 1001*b4a7ce06SEric Joyner ret = I40E_SUCCESS; 1002*b4a7ce06SEric Joyner } 1003*b4a7ce06SEric Joyner 1004*b4a7ce06SEric Joyner i40e_free_virt_mem(hw, &mem); 1005*b4a7ce06SEric Joyner return ret; 1006*b4a7ce06SEric Joyner } 1007*b4a7ce06SEric Joyner 1008*b4a7ce06SEric Joyner 1009*b4a7ce06SEric Joyner /** 1010ceebc2f3SEric Joyner * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 1011ceebc2f3SEric Joyner * @tlv: Fill the ETS config data in IEEE format 1012ceebc2f3SEric Joyner * @dcbcfg: Local store which holds the DCB Config 1013ceebc2f3SEric Joyner * 1014ceebc2f3SEric Joyner * Prepare IEEE 802.1Qaz ETS CFG TLV 1015ceebc2f3SEric Joyner **/ 1016ceebc2f3SEric Joyner static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv, 1017ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 1018ceebc2f3SEric Joyner { 1019ceebc2f3SEric Joyner u8 priority0, priority1, maxtcwilling = 0; 1020ceebc2f3SEric Joyner struct i40e_dcb_ets_config *etscfg; 1021ceebc2f3SEric Joyner u16 offset = 0, typelength, i; 1022ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 1023ceebc2f3SEric Joyner u32 ouisubtype; 1024ceebc2f3SEric Joyner 1025ceebc2f3SEric Joyner typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1026ceebc2f3SEric Joyner I40E_IEEE_ETS_TLV_LENGTH); 1027ceebc2f3SEric Joyner tlv->typelength = I40E_HTONS(typelength); 1028ceebc2f3SEric Joyner 1029ceebc2f3SEric Joyner ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1030ceebc2f3SEric Joyner I40E_IEEE_SUBTYPE_ETS_CFG); 1031ceebc2f3SEric Joyner tlv->ouisubtype = I40E_HTONL(ouisubtype); 1032ceebc2f3SEric Joyner 1033ceebc2f3SEric Joyner /* First Octet post subtype 1034ceebc2f3SEric Joyner * -------------------------- 1035ceebc2f3SEric Joyner * |will-|CBS | Re- | Max | 1036ceebc2f3SEric Joyner * |ing | |served| TCs | 1037ceebc2f3SEric Joyner * -------------------------- 1038ceebc2f3SEric Joyner * |1bit | 1bit|3 bits|3bits| 1039ceebc2f3SEric Joyner */ 1040ceebc2f3SEric Joyner etscfg = &dcbcfg->etscfg; 1041ceebc2f3SEric Joyner if (etscfg->willing) 1042ceebc2f3SEric Joyner maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT); 1043ceebc2f3SEric Joyner maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK; 1044ceebc2f3SEric Joyner buf[offset] = maxtcwilling; 1045ceebc2f3SEric Joyner 1046ceebc2f3SEric Joyner /* Move offset to Priority Assignment Table */ 1047ceebc2f3SEric Joyner offset++; 1048ceebc2f3SEric Joyner 1049ceebc2f3SEric Joyner /* Priority Assignment Table (4 octets) 1050ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 1051ceebc2f3SEric Joyner * ----------------------------------------- 1052ceebc2f3SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1053ceebc2f3SEric Joyner * ----------------------------------------- 1054ceebc2f3SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1055ceebc2f3SEric Joyner * ----------------------------------------- 1056ceebc2f3SEric Joyner */ 1057ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 1058ceebc2f3SEric Joyner priority0 = etscfg->prioritytable[i * 2] & 0xF; 1059ceebc2f3SEric Joyner priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF; 1060ceebc2f3SEric Joyner buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) | 1061ceebc2f3SEric Joyner priority1; 1062ceebc2f3SEric Joyner offset++; 1063ceebc2f3SEric Joyner } 1064ceebc2f3SEric Joyner 1065ceebc2f3SEric Joyner /* TC Bandwidth Table (8 octets) 1066ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1067ceebc2f3SEric Joyner * --------------------------------- 1068ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1069ceebc2f3SEric Joyner * --------------------------------- 1070ceebc2f3SEric Joyner */ 1071ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1072ceebc2f3SEric Joyner buf[offset++] = etscfg->tcbwtable[i]; 1073ceebc2f3SEric Joyner 1074ceebc2f3SEric Joyner /* TSA Assignment Table (8 octets) 1075ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1076ceebc2f3SEric Joyner * --------------------------------- 1077ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1078ceebc2f3SEric Joyner * --------------------------------- 1079ceebc2f3SEric Joyner */ 1080ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1081ceebc2f3SEric Joyner buf[offset++] = etscfg->tsatable[i]; 1082ceebc2f3SEric Joyner } 1083ceebc2f3SEric Joyner 1084ceebc2f3SEric Joyner /** 1085ceebc2f3SEric Joyner * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 1086ceebc2f3SEric Joyner * @tlv: Fill ETS Recommended TLV in IEEE format 1087ceebc2f3SEric Joyner * @dcbcfg: Local store which holds the DCB Config 1088ceebc2f3SEric Joyner * 1089ceebc2f3SEric Joyner * Prepare IEEE 802.1Qaz ETS REC TLV 1090ceebc2f3SEric Joyner **/ 1091ceebc2f3SEric Joyner static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv, 1092ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 1093ceebc2f3SEric Joyner { 1094ceebc2f3SEric Joyner struct i40e_dcb_ets_config *etsrec; 1095ceebc2f3SEric Joyner u16 offset = 0, typelength, i; 1096ceebc2f3SEric Joyner u8 priority0, priority1; 1097ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 1098ceebc2f3SEric Joyner u32 ouisubtype; 1099ceebc2f3SEric Joyner 1100ceebc2f3SEric Joyner typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1101ceebc2f3SEric Joyner I40E_IEEE_ETS_TLV_LENGTH); 1102ceebc2f3SEric Joyner tlv->typelength = I40E_HTONS(typelength); 1103ceebc2f3SEric Joyner 1104ceebc2f3SEric Joyner ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1105ceebc2f3SEric Joyner I40E_IEEE_SUBTYPE_ETS_REC); 1106ceebc2f3SEric Joyner tlv->ouisubtype = I40E_HTONL(ouisubtype); 1107ceebc2f3SEric Joyner 1108ceebc2f3SEric Joyner etsrec = &dcbcfg->etsrec; 1109ceebc2f3SEric Joyner /* First Octet is reserved */ 1110ceebc2f3SEric Joyner /* Move offset to Priority Assignment Table */ 1111ceebc2f3SEric Joyner offset++; 1112ceebc2f3SEric Joyner 1113ceebc2f3SEric Joyner /* Priority Assignment Table (4 octets) 1114ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 1115ceebc2f3SEric Joyner * ----------------------------------------- 1116ceebc2f3SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1117ceebc2f3SEric Joyner * ----------------------------------------- 1118ceebc2f3SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1119ceebc2f3SEric Joyner * ----------------------------------------- 1120ceebc2f3SEric Joyner */ 1121ceebc2f3SEric Joyner for (i = 0; i < 4; i++) { 1122ceebc2f3SEric Joyner priority0 = etsrec->prioritytable[i * 2] & 0xF; 1123ceebc2f3SEric Joyner priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF; 1124ceebc2f3SEric Joyner buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) | 1125ceebc2f3SEric Joyner priority1; 1126ceebc2f3SEric Joyner offset++; 1127ceebc2f3SEric Joyner } 1128ceebc2f3SEric Joyner 1129ceebc2f3SEric Joyner /* TC Bandwidth Table (8 octets) 1130ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1131ceebc2f3SEric Joyner * --------------------------------- 1132ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1133ceebc2f3SEric Joyner * --------------------------------- 1134ceebc2f3SEric Joyner */ 1135ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1136ceebc2f3SEric Joyner buf[offset++] = etsrec->tcbwtable[i]; 1137ceebc2f3SEric Joyner 1138ceebc2f3SEric Joyner /* TSA Assignment Table (8 octets) 1139ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1140ceebc2f3SEric Joyner * --------------------------------- 1141ceebc2f3SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1142ceebc2f3SEric Joyner * --------------------------------- 1143ceebc2f3SEric Joyner */ 1144ceebc2f3SEric Joyner for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1145ceebc2f3SEric Joyner buf[offset++] = etsrec->tsatable[i]; 1146ceebc2f3SEric Joyner } 1147ceebc2f3SEric Joyner 1148ceebc2f3SEric Joyner /** 1149ceebc2f3SEric Joyner * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 1150ceebc2f3SEric Joyner * @tlv: Fill PFC TLV in IEEE format 1151ceebc2f3SEric Joyner * @dcbcfg: Local store to get PFC CFG data 1152ceebc2f3SEric Joyner * 1153ceebc2f3SEric Joyner * Prepare IEEE 802.1Qaz PFC CFG TLV 1154ceebc2f3SEric Joyner **/ 1155ceebc2f3SEric Joyner static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv, 1156ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 1157ceebc2f3SEric Joyner { 1158ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 1159ceebc2f3SEric Joyner u32 ouisubtype; 1160ceebc2f3SEric Joyner u16 typelength; 1161ceebc2f3SEric Joyner 1162ceebc2f3SEric Joyner typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1163ceebc2f3SEric Joyner I40E_IEEE_PFC_TLV_LENGTH); 1164ceebc2f3SEric Joyner tlv->typelength = I40E_HTONS(typelength); 1165ceebc2f3SEric Joyner 1166ceebc2f3SEric Joyner ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1167ceebc2f3SEric Joyner I40E_IEEE_SUBTYPE_PFC_CFG); 1168ceebc2f3SEric Joyner tlv->ouisubtype = I40E_HTONL(ouisubtype); 1169ceebc2f3SEric Joyner 1170ceebc2f3SEric Joyner /* ---------------------------------------- 1171ceebc2f3SEric Joyner * |will-|MBC | Re- | PFC | PFC Enable | 1172ceebc2f3SEric Joyner * |ing | |served| cap | | 1173ceebc2f3SEric Joyner * ----------------------------------------- 1174ceebc2f3SEric Joyner * |1bit | 1bit|2 bits|4bits| 1 octet | 1175ceebc2f3SEric Joyner */ 1176ceebc2f3SEric Joyner if (dcbcfg->pfc.willing) 1177ceebc2f3SEric Joyner buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT); 1178ceebc2f3SEric Joyner 1179ceebc2f3SEric Joyner if (dcbcfg->pfc.mbc) 1180ceebc2f3SEric Joyner buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT); 1181ceebc2f3SEric Joyner 1182ceebc2f3SEric Joyner buf[0] |= dcbcfg->pfc.pfccap & 0xF; 1183ceebc2f3SEric Joyner buf[1] = dcbcfg->pfc.pfcenable; 1184ceebc2f3SEric Joyner } 1185ceebc2f3SEric Joyner 1186ceebc2f3SEric Joyner /** 1187ceebc2f3SEric Joyner * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 1188ceebc2f3SEric Joyner * @tlv: Fill APP TLV in IEEE format 1189ceebc2f3SEric Joyner * @dcbcfg: Local store to get APP CFG data 1190ceebc2f3SEric Joyner * 1191ceebc2f3SEric Joyner * Prepare IEEE 802.1Qaz APP CFG TLV 1192ceebc2f3SEric Joyner **/ 1193ceebc2f3SEric Joyner static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv, 1194ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 1195ceebc2f3SEric Joyner { 1196ceebc2f3SEric Joyner u16 typelength, length, offset = 0; 1197ceebc2f3SEric Joyner u8 priority, selector, i = 0; 1198ceebc2f3SEric Joyner u8 *buf = tlv->tlvinfo; 1199ceebc2f3SEric Joyner u32 ouisubtype; 1200ceebc2f3SEric Joyner 1201ceebc2f3SEric Joyner /* No APP TLVs then just return */ 1202ceebc2f3SEric Joyner if (dcbcfg->numapps == 0) 1203ceebc2f3SEric Joyner return; 1204ceebc2f3SEric Joyner ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1205ceebc2f3SEric Joyner I40E_IEEE_SUBTYPE_APP_PRI); 1206ceebc2f3SEric Joyner tlv->ouisubtype = I40E_HTONL(ouisubtype); 1207ceebc2f3SEric Joyner 1208ceebc2f3SEric Joyner /* Move offset to App Priority Table */ 1209ceebc2f3SEric Joyner offset++; 1210ceebc2f3SEric Joyner /* Application Priority Table (3 octets) 1211ceebc2f3SEric Joyner * Octets:| 1 | 2 | 3 | 1212ceebc2f3SEric Joyner * ----------------------------------------- 1213ceebc2f3SEric Joyner * |Priority|Rsrvd| Sel | Protocol ID | 1214ceebc2f3SEric Joyner * ----------------------------------------- 1215ceebc2f3SEric Joyner * Bits:|23 21|20 19|18 16|15 0| 1216ceebc2f3SEric Joyner * ----------------------------------------- 1217ceebc2f3SEric Joyner */ 1218ceebc2f3SEric Joyner while (i < dcbcfg->numapps) { 1219ceebc2f3SEric Joyner priority = dcbcfg->app[i].priority & 0x7; 1220ceebc2f3SEric Joyner selector = dcbcfg->app[i].selector & 0x7; 1221ceebc2f3SEric Joyner buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector; 1222ceebc2f3SEric Joyner buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF; 1223ceebc2f3SEric Joyner buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF; 1224ceebc2f3SEric Joyner /* Move to next app */ 1225ceebc2f3SEric Joyner offset += 3; 1226ceebc2f3SEric Joyner i++; 1227ceebc2f3SEric Joyner if (i >= I40E_DCBX_MAX_APPS) 1228ceebc2f3SEric Joyner break; 1229ceebc2f3SEric Joyner } 1230ceebc2f3SEric Joyner /* length includes size of ouisubtype + 1 reserved + 3*numapps */ 1231ceebc2f3SEric Joyner length = sizeof(tlv->ouisubtype) + 1 + (i*3); 1232ceebc2f3SEric Joyner typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1233ceebc2f3SEric Joyner (length & 0x1FF)); 1234ceebc2f3SEric Joyner tlv->typelength = I40E_HTONS(typelength); 1235ceebc2f3SEric Joyner } 1236ceebc2f3SEric Joyner 1237ceebc2f3SEric Joyner /** 1238ceebc2f3SEric Joyner * i40e_add_dcb_tlv - Add all IEEE TLVs 1239ceebc2f3SEric Joyner * @tlv: pointer to org tlv 1240ceebc2f3SEric Joyner * 1241ceebc2f3SEric Joyner * add tlv information 1242ceebc2f3SEric Joyner **/ 1243ceebc2f3SEric Joyner static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv, 1244ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg, 1245ceebc2f3SEric Joyner u16 tlvid) 1246ceebc2f3SEric Joyner { 1247ceebc2f3SEric Joyner switch (tlvid) { 1248ceebc2f3SEric Joyner case I40E_IEEE_TLV_ID_ETS_CFG: 1249ceebc2f3SEric Joyner i40e_add_ieee_ets_tlv(tlv, dcbcfg); 1250ceebc2f3SEric Joyner break; 1251ceebc2f3SEric Joyner case I40E_IEEE_TLV_ID_ETS_REC: 1252ceebc2f3SEric Joyner i40e_add_ieee_etsrec_tlv(tlv, dcbcfg); 1253ceebc2f3SEric Joyner break; 1254ceebc2f3SEric Joyner case I40E_IEEE_TLV_ID_PFC_CFG: 1255ceebc2f3SEric Joyner i40e_add_ieee_pfc_tlv(tlv, dcbcfg); 1256ceebc2f3SEric Joyner break; 1257ceebc2f3SEric Joyner case I40E_IEEE_TLV_ID_APP_PRI: 1258ceebc2f3SEric Joyner i40e_add_ieee_app_pri_tlv(tlv, dcbcfg); 1259ceebc2f3SEric Joyner break; 1260ceebc2f3SEric Joyner default: 1261ceebc2f3SEric Joyner break; 1262ceebc2f3SEric Joyner } 1263ceebc2f3SEric Joyner } 1264ceebc2f3SEric Joyner 1265ceebc2f3SEric Joyner /** 1266ceebc2f3SEric Joyner * i40e_set_dcb_config - Set the local LLDP MIB to FW 1267ceebc2f3SEric Joyner * @hw: pointer to the hw struct 1268ceebc2f3SEric Joyner * 1269ceebc2f3SEric Joyner * Set DCB configuration to the Firmware 1270ceebc2f3SEric Joyner **/ 1271ceebc2f3SEric Joyner enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw) 1272ceebc2f3SEric Joyner { 1273ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 1274ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg; 1275ceebc2f3SEric Joyner struct i40e_virt_mem mem; 1276ceebc2f3SEric Joyner u8 mib_type, *lldpmib; 1277ceebc2f3SEric Joyner u16 miblen; 1278ceebc2f3SEric Joyner 1279ceebc2f3SEric Joyner /* update the hw local config */ 1280ceebc2f3SEric Joyner dcbcfg = &hw->local_dcbx_config; 1281ceebc2f3SEric Joyner /* Allocate the LLDPDU */ 1282ceebc2f3SEric Joyner ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 1283ceebc2f3SEric Joyner if (ret) 1284ceebc2f3SEric Joyner return ret; 1285ceebc2f3SEric Joyner 1286ceebc2f3SEric Joyner mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB; 1287ceebc2f3SEric Joyner if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) { 1288ceebc2f3SEric Joyner mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS << 1289ceebc2f3SEric Joyner SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT; 1290ceebc2f3SEric Joyner } 1291ceebc2f3SEric Joyner lldpmib = (u8 *)mem.va; 1292ceebc2f3SEric Joyner ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg); 1293ceebc2f3SEric Joyner ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL); 1294ceebc2f3SEric Joyner 1295ceebc2f3SEric Joyner i40e_free_virt_mem(hw, &mem); 1296ceebc2f3SEric Joyner return ret; 1297ceebc2f3SEric Joyner } 1298ceebc2f3SEric Joyner 1299ceebc2f3SEric Joyner /** 1300ceebc2f3SEric Joyner * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format 1301*b4a7ce06SEric Joyner * @lldpmib: pointer to mib to be output 1302*b4a7ce06SEric Joyner * @miblen: pointer to u16 for length of lldpmib 1303ceebc2f3SEric Joyner * @dcbcfg: store for LLDPDU data 1304ceebc2f3SEric Joyner * 1305ceebc2f3SEric Joyner * send DCB configuration to FW 1306ceebc2f3SEric Joyner **/ 1307ceebc2f3SEric Joyner enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen, 1308ceebc2f3SEric Joyner struct i40e_dcbx_config *dcbcfg) 1309ceebc2f3SEric Joyner { 1310ceebc2f3SEric Joyner u16 length, offset = 0, tlvid = I40E_TLV_ID_START; 1311ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 1312ceebc2f3SEric Joyner struct i40e_lldp_org_tlv *tlv; 1313ceebc2f3SEric Joyner u16 typelength; 1314ceebc2f3SEric Joyner 1315ceebc2f3SEric Joyner tlv = (struct i40e_lldp_org_tlv *)lldpmib; 1316ceebc2f3SEric Joyner while (1) { 1317ceebc2f3SEric Joyner i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++); 1318ceebc2f3SEric Joyner typelength = I40E_NTOHS(tlv->typelength); 1319ceebc2f3SEric Joyner length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 1320ceebc2f3SEric Joyner I40E_LLDP_TLV_LEN_SHIFT); 1321ceebc2f3SEric Joyner if (length) 1322ceebc2f3SEric Joyner offset += length + 2; 1323ceebc2f3SEric Joyner /* END TLV or beyond LLDPDU size */ 1324ceebc2f3SEric Joyner if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) || 1325ceebc2f3SEric Joyner (offset > I40E_LLDPDU_SIZE)) 1326ceebc2f3SEric Joyner break; 1327ceebc2f3SEric Joyner /* Move to next TLV */ 1328ceebc2f3SEric Joyner if (length) 1329ceebc2f3SEric Joyner tlv = (struct i40e_lldp_org_tlv *)((char *)tlv + 1330ceebc2f3SEric Joyner sizeof(tlv->typelength) + length); 1331ceebc2f3SEric Joyner } 1332ceebc2f3SEric Joyner *miblen = offset; 1333ceebc2f3SEric Joyner return ret; 1334ceebc2f3SEric Joyner } 1335ceebc2f3SEric Joyner 1336ceebc2f3SEric Joyner 1337ceebc2f3SEric Joyner /** 1338ceebc2f3SEric Joyner * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM 1339ceebc2f3SEric Joyner * @hw: pointer to the HW structure 1340ceebc2f3SEric Joyner * @lldp_cfg: pointer to hold lldp configuration variables 1341ceebc2f3SEric Joyner * @module: address of the module pointer 1342ceebc2f3SEric Joyner * @word_offset: offset of LLDP configuration 1343ceebc2f3SEric Joyner * 1344ceebc2f3SEric Joyner * Reads the LLDP configuration data from NVM using passed addresses 1345ceebc2f3SEric Joyner **/ 1346ceebc2f3SEric Joyner static enum i40e_status_code _i40e_read_lldp_cfg(struct i40e_hw *hw, 1347ceebc2f3SEric Joyner struct i40e_lldp_variables *lldp_cfg, 1348ceebc2f3SEric Joyner u8 module, u32 word_offset) 1349ceebc2f3SEric Joyner { 1350ceebc2f3SEric Joyner u32 address, offset = (2 * word_offset); 1351ceebc2f3SEric Joyner enum i40e_status_code ret; 1352ceebc2f3SEric Joyner __le16 raw_mem; 1353ceebc2f3SEric Joyner u16 mem; 1354ceebc2f3SEric Joyner 1355ceebc2f3SEric Joyner ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1356ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1357ceebc2f3SEric Joyner return ret; 1358ceebc2f3SEric Joyner 1359ceebc2f3SEric Joyner ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem, 1360ceebc2f3SEric Joyner TRUE, NULL); 1361ceebc2f3SEric Joyner i40e_release_nvm(hw); 1362ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1363ceebc2f3SEric Joyner return ret; 1364ceebc2f3SEric Joyner 1365ceebc2f3SEric Joyner mem = LE16_TO_CPU(raw_mem); 1366ceebc2f3SEric Joyner /* Check if this pointer needs to be read in word size or 4K sector 1367ceebc2f3SEric Joyner * units. 1368ceebc2f3SEric Joyner */ 1369ceebc2f3SEric Joyner if (mem & I40E_PTR_TYPE) 1370ceebc2f3SEric Joyner address = (0x7FFF & mem) * 4096; 1371ceebc2f3SEric Joyner else 1372ceebc2f3SEric Joyner address = (0x7FFF & mem) * 2; 1373ceebc2f3SEric Joyner 1374ceebc2f3SEric Joyner ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1375ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1376ceebc2f3SEric Joyner goto err_lldp_cfg; 1377ceebc2f3SEric Joyner 1378ceebc2f3SEric Joyner ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem, 1379ceebc2f3SEric Joyner TRUE, NULL); 1380ceebc2f3SEric Joyner i40e_release_nvm(hw); 1381ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1382ceebc2f3SEric Joyner return ret; 1383ceebc2f3SEric Joyner 1384ceebc2f3SEric Joyner mem = LE16_TO_CPU(raw_mem); 1385ceebc2f3SEric Joyner offset = mem + word_offset; 1386ceebc2f3SEric Joyner offset *= 2; 1387ceebc2f3SEric Joyner 1388ceebc2f3SEric Joyner ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1389ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1390ceebc2f3SEric Joyner goto err_lldp_cfg; 1391ceebc2f3SEric Joyner 1392ceebc2f3SEric Joyner ret = i40e_aq_read_nvm(hw, 0, address + offset, 1393ceebc2f3SEric Joyner sizeof(struct i40e_lldp_variables), lldp_cfg, 1394ceebc2f3SEric Joyner TRUE, NULL); 1395ceebc2f3SEric Joyner i40e_release_nvm(hw); 1396ceebc2f3SEric Joyner 1397ceebc2f3SEric Joyner err_lldp_cfg: 1398ceebc2f3SEric Joyner return ret; 1399ceebc2f3SEric Joyner } 1400ceebc2f3SEric Joyner 1401ceebc2f3SEric Joyner /** 1402ceebc2f3SEric Joyner * i40e_read_lldp_cfg - read LLDP Configuration data from NVM 1403ceebc2f3SEric Joyner * @hw: pointer to the HW structure 1404ceebc2f3SEric Joyner * @lldp_cfg: pointer to hold lldp configuration variables 1405ceebc2f3SEric Joyner * 1406ceebc2f3SEric Joyner * Reads the LLDP configuration data from NVM 1407ceebc2f3SEric Joyner **/ 1408ceebc2f3SEric Joyner enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw, 1409ceebc2f3SEric Joyner struct i40e_lldp_variables *lldp_cfg) 1410ceebc2f3SEric Joyner { 1411ceebc2f3SEric Joyner enum i40e_status_code ret = I40E_SUCCESS; 1412ceebc2f3SEric Joyner u32 mem; 1413ceebc2f3SEric Joyner 1414ceebc2f3SEric Joyner if (!lldp_cfg) 1415ceebc2f3SEric Joyner return I40E_ERR_PARAM; 1416ceebc2f3SEric Joyner 1417ceebc2f3SEric Joyner ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1418ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1419ceebc2f3SEric Joyner return ret; 1420ceebc2f3SEric Joyner 1421ceebc2f3SEric Joyner ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem), 1422ceebc2f3SEric Joyner &mem, TRUE, NULL); 1423ceebc2f3SEric Joyner i40e_release_nvm(hw); 1424ceebc2f3SEric Joyner if (ret != I40E_SUCCESS) 1425ceebc2f3SEric Joyner return ret; 1426ceebc2f3SEric Joyner 1427ceebc2f3SEric Joyner /* Read a bit that holds information whether we are running flat or 1428ceebc2f3SEric Joyner * structured NVM image. Flat image has LLDP configuration in shadow 1429ceebc2f3SEric Joyner * ram, so there is a need to pass different addresses for both cases. 1430ceebc2f3SEric Joyner */ 1431ceebc2f3SEric Joyner if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) { 1432ceebc2f3SEric Joyner /* Flat NVM case */ 1433ceebc2f3SEric Joyner ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR, 1434ceebc2f3SEric Joyner I40E_SR_LLDP_CFG_PTR); 1435ceebc2f3SEric Joyner } else { 1436ceebc2f3SEric Joyner /* Good old structured NVM image */ 1437ceebc2f3SEric Joyner ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR, 1438ceebc2f3SEric Joyner I40E_NVM_LLDP_CFG_PTR); 1439ceebc2f3SEric Joyner } 1440ceebc2f3SEric Joyner 1441ceebc2f3SEric Joyner return ret; 1442ceebc2f3SEric Joyner } 1443