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