1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2013 - 2021 Intel Corporation. */ 3 4 #include "i40e_adminq.h" 5 #include "i40e_prototype.h" 6 #include "i40e_dcb.h" 7 8 /** 9 * i40e_get_dcbx_status 10 * @hw: pointer to the hw struct 11 * @status: Embedded DCBX Engine Status 12 * 13 * Get the DCBX status from the Firmware 14 **/ 15 i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status) 16 { 17 u32 reg; 18 19 if (!status) 20 return I40E_ERR_PARAM; 21 22 reg = rd32(hw, I40E_PRTDCB_GENS); 23 *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >> 24 I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT); 25 26 return 0; 27 } 28 29 /** 30 * i40e_parse_ieee_etscfg_tlv 31 * @tlv: IEEE 802.1Qaz ETS CFG TLV 32 * @dcbcfg: Local store to update ETS CFG data 33 * 34 * Parses IEEE 802.1Qaz ETS CFG TLV 35 **/ 36 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv, 37 struct i40e_dcbx_config *dcbcfg) 38 { 39 struct i40e_dcb_ets_config *etscfg; 40 u8 *buf = tlv->tlvinfo; 41 u16 offset = 0; 42 u8 priority; 43 int i; 44 45 /* First Octet post subtype 46 * -------------------------- 47 * |will-|CBS | Re- | Max | 48 * |ing | |served| TCs | 49 * -------------------------- 50 * |1bit | 1bit|3 bits|3bits| 51 */ 52 etscfg = &dcbcfg->etscfg; 53 etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >> 54 I40E_IEEE_ETS_WILLING_SHIFT); 55 etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >> 56 I40E_IEEE_ETS_CBS_SHIFT); 57 etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >> 58 I40E_IEEE_ETS_MAXTC_SHIFT); 59 60 /* Move offset to Priority Assignment Table */ 61 offset++; 62 63 /* Priority Assignment Table (4 octets) 64 * Octets:| 1 | 2 | 3 | 4 | 65 * ----------------------------------------- 66 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 67 * ----------------------------------------- 68 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 69 * ----------------------------------------- 70 */ 71 for (i = 0; i < 4; i++) { 72 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> 73 I40E_IEEE_ETS_PRIO_1_SHIFT); 74 etscfg->prioritytable[i * 2] = priority; 75 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> 76 I40E_IEEE_ETS_PRIO_0_SHIFT); 77 etscfg->prioritytable[i * 2 + 1] = priority; 78 offset++; 79 } 80 81 /* TC Bandwidth Table (8 octets) 82 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 83 * --------------------------------- 84 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 85 * --------------------------------- 86 */ 87 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 88 etscfg->tcbwtable[i] = buf[offset++]; 89 90 /* TSA Assignment Table (8 octets) 91 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 92 * --------------------------------- 93 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 94 * --------------------------------- 95 */ 96 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 97 etscfg->tsatable[i] = buf[offset++]; 98 } 99 100 /** 101 * i40e_parse_ieee_etsrec_tlv 102 * @tlv: IEEE 802.1Qaz ETS REC TLV 103 * @dcbcfg: Local store to update ETS REC data 104 * 105 * Parses IEEE 802.1Qaz ETS REC TLV 106 **/ 107 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv, 108 struct i40e_dcbx_config *dcbcfg) 109 { 110 u8 *buf = tlv->tlvinfo; 111 u16 offset = 0; 112 u8 priority; 113 int i; 114 115 /* Move offset to priority table */ 116 offset++; 117 118 /* Priority Assignment Table (4 octets) 119 * Octets:| 1 | 2 | 3 | 4 | 120 * ----------------------------------------- 121 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 122 * ----------------------------------------- 123 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 124 * ----------------------------------------- 125 */ 126 for (i = 0; i < 4; i++) { 127 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> 128 I40E_IEEE_ETS_PRIO_1_SHIFT); 129 dcbcfg->etsrec.prioritytable[i*2] = priority; 130 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> 131 I40E_IEEE_ETS_PRIO_0_SHIFT); 132 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority; 133 offset++; 134 } 135 136 /* TC Bandwidth Table (8 octets) 137 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 138 * --------------------------------- 139 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 140 * --------------------------------- 141 */ 142 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 143 dcbcfg->etsrec.tcbwtable[i] = buf[offset++]; 144 145 /* TSA Assignment Table (8 octets) 146 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 147 * --------------------------------- 148 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 149 * --------------------------------- 150 */ 151 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 152 dcbcfg->etsrec.tsatable[i] = buf[offset++]; 153 } 154 155 /** 156 * i40e_parse_ieee_pfccfg_tlv 157 * @tlv: IEEE 802.1Qaz PFC CFG TLV 158 * @dcbcfg: Local store to update PFC CFG data 159 * 160 * Parses IEEE 802.1Qaz PFC CFG TLV 161 **/ 162 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv, 163 struct i40e_dcbx_config *dcbcfg) 164 { 165 u8 *buf = tlv->tlvinfo; 166 167 /* ---------------------------------------- 168 * |will-|MBC | Re- | PFC | PFC Enable | 169 * |ing | |served| cap | | 170 * ----------------------------------------- 171 * |1bit | 1bit|2 bits|4bits| 1 octet | 172 */ 173 dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >> 174 I40E_IEEE_PFC_WILLING_SHIFT); 175 dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >> 176 I40E_IEEE_PFC_MBC_SHIFT); 177 dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >> 178 I40E_IEEE_PFC_CAP_SHIFT); 179 dcbcfg->pfc.pfcenable = buf[1]; 180 } 181 182 /** 183 * i40e_parse_ieee_app_tlv 184 * @tlv: IEEE 802.1Qaz APP TLV 185 * @dcbcfg: Local store to update APP PRIO data 186 * 187 * Parses IEEE 802.1Qaz APP PRIO TLV 188 **/ 189 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv, 190 struct i40e_dcbx_config *dcbcfg) 191 { 192 u16 typelength; 193 u16 offset = 0; 194 u16 length; 195 int i = 0; 196 u8 *buf; 197 198 typelength = ntohs(tlv->typelength); 199 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 200 I40E_LLDP_TLV_LEN_SHIFT); 201 buf = tlv->tlvinfo; 202 203 /* The App priority table starts 5 octets after TLV header */ 204 length -= (sizeof(tlv->ouisubtype) + 1); 205 206 /* Move offset to App Priority Table */ 207 offset++; 208 209 /* Application Priority Table (3 octets) 210 * Octets:| 1 | 2 | 3 | 211 * ----------------------------------------- 212 * |Priority|Rsrvd| Sel | Protocol ID | 213 * ----------------------------------------- 214 * Bits:|23 21|20 19|18 16|15 0| 215 * ----------------------------------------- 216 */ 217 while (offset < length) { 218 dcbcfg->app[i].priority = (u8)((buf[offset] & 219 I40E_IEEE_APP_PRIO_MASK) >> 220 I40E_IEEE_APP_PRIO_SHIFT); 221 dcbcfg->app[i].selector = (u8)((buf[offset] & 222 I40E_IEEE_APP_SEL_MASK) >> 223 I40E_IEEE_APP_SEL_SHIFT); 224 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) | 225 buf[offset + 2]; 226 /* Move to next app */ 227 offset += 3; 228 i++; 229 if (i >= I40E_DCBX_MAX_APPS) 230 break; 231 } 232 233 dcbcfg->numapps = i; 234 } 235 236 /** 237 * i40e_parse_ieee_etsrec_tlv 238 * @tlv: IEEE 802.1Qaz TLV 239 * @dcbcfg: Local store to update ETS REC data 240 * 241 * Get the TLV subtype and send it to parsing function 242 * based on the subtype value 243 **/ 244 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv, 245 struct i40e_dcbx_config *dcbcfg) 246 { 247 u32 ouisubtype; 248 u8 subtype; 249 250 ouisubtype = ntohl(tlv->ouisubtype); 251 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> 252 I40E_LLDP_TLV_SUBTYPE_SHIFT); 253 switch (subtype) { 254 case I40E_IEEE_SUBTYPE_ETS_CFG: 255 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg); 256 break; 257 case I40E_IEEE_SUBTYPE_ETS_REC: 258 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg); 259 break; 260 case I40E_IEEE_SUBTYPE_PFC_CFG: 261 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg); 262 break; 263 case I40E_IEEE_SUBTYPE_APP_PRI: 264 i40e_parse_ieee_app_tlv(tlv, dcbcfg); 265 break; 266 default: 267 break; 268 } 269 } 270 271 /** 272 * i40e_parse_cee_pgcfg_tlv 273 * @tlv: CEE DCBX PG CFG TLV 274 * @dcbcfg: Local store to update ETS CFG data 275 * 276 * Parses CEE DCBX PG CFG TLV 277 **/ 278 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv, 279 struct i40e_dcbx_config *dcbcfg) 280 { 281 struct i40e_dcb_ets_config *etscfg; 282 u8 *buf = tlv->tlvinfo; 283 u16 offset = 0; 284 u8 priority; 285 int i; 286 287 etscfg = &dcbcfg->etscfg; 288 289 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) 290 etscfg->willing = 1; 291 292 etscfg->cbs = 0; 293 /* Priority Group Table (4 octets) 294 * Octets:| 1 | 2 | 3 | 4 | 295 * ----------------------------------------- 296 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 297 * ----------------------------------------- 298 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 299 * ----------------------------------------- 300 */ 301 for (i = 0; i < 4; i++) { 302 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >> 303 I40E_CEE_PGID_PRIO_1_SHIFT); 304 etscfg->prioritytable[i * 2] = priority; 305 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >> 306 I40E_CEE_PGID_PRIO_0_SHIFT); 307 etscfg->prioritytable[i * 2 + 1] = priority; 308 offset++; 309 } 310 311 /* PG Percentage Table (8 octets) 312 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 313 * --------------------------------- 314 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7| 315 * --------------------------------- 316 */ 317 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 318 etscfg->tcbwtable[i] = buf[offset++]; 319 320 /* Number of TCs supported (1 octet) */ 321 etscfg->maxtcs = buf[offset]; 322 } 323 324 /** 325 * i40e_parse_cee_pfccfg_tlv 326 * @tlv: CEE DCBX PFC CFG TLV 327 * @dcbcfg: Local store to update PFC CFG data 328 * 329 * Parses CEE DCBX PFC CFG TLV 330 **/ 331 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv, 332 struct i40e_dcbx_config *dcbcfg) 333 { 334 u8 *buf = tlv->tlvinfo; 335 336 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) 337 dcbcfg->pfc.willing = 1; 338 339 /* ------------------------ 340 * | PFC Enable | PFC TCs | 341 * ------------------------ 342 * | 1 octet | 1 octet | 343 */ 344 dcbcfg->pfc.pfcenable = buf[0]; 345 dcbcfg->pfc.pfccap = buf[1]; 346 } 347 348 /** 349 * i40e_parse_cee_app_tlv 350 * @tlv: CEE DCBX APP TLV 351 * @dcbcfg: Local store to update APP PRIO data 352 * 353 * Parses CEE DCBX APP PRIO TLV 354 **/ 355 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, 356 struct i40e_dcbx_config *dcbcfg) 357 { 358 u16 length, typelength, offset = 0; 359 struct i40e_cee_app_prio *app; 360 u8 i; 361 362 typelength = ntohs(tlv->hdr.typelen); 363 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 364 I40E_LLDP_TLV_LEN_SHIFT); 365 366 dcbcfg->numapps = length / sizeof(*app); 367 368 if (!dcbcfg->numapps) 369 return; 370 if (dcbcfg->numapps > I40E_DCBX_MAX_APPS) 371 dcbcfg->numapps = I40E_DCBX_MAX_APPS; 372 373 for (i = 0; i < dcbcfg->numapps; i++) { 374 u8 up, selector; 375 376 app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset); 377 for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) { 378 if (app->prio_map & BIT(up)) 379 break; 380 } 381 dcbcfg->app[i].priority = up; 382 383 /* Get Selector from lower 2 bits, and convert to IEEE */ 384 selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK); 385 switch (selector) { 386 case I40E_CEE_APP_SEL_ETHTYPE: 387 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 388 break; 389 case I40E_CEE_APP_SEL_TCPIP: 390 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; 391 break; 392 default: 393 /* Keep selector as it is for unknown types */ 394 dcbcfg->app[i].selector = selector; 395 } 396 397 dcbcfg->app[i].protocolid = ntohs(app->protocol); 398 /* Move to next app */ 399 offset += sizeof(*app); 400 } 401 } 402 403 /** 404 * i40e_parse_cee_tlv 405 * @tlv: CEE DCBX TLV 406 * @dcbcfg: Local store to update DCBX config data 407 * 408 * Get the TLV subtype and send it to parsing function 409 * based on the subtype value 410 **/ 411 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv, 412 struct i40e_dcbx_config *dcbcfg) 413 { 414 u16 len, tlvlen, sublen, typelength; 415 struct i40e_cee_feat_tlv *sub_tlv; 416 u8 subtype, feat_tlv_count = 0; 417 u32 ouisubtype; 418 419 ouisubtype = ntohl(tlv->ouisubtype); 420 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> 421 I40E_LLDP_TLV_SUBTYPE_SHIFT); 422 /* Return if not CEE DCBX */ 423 if (subtype != I40E_CEE_DCBX_TYPE) 424 return; 425 426 typelength = ntohs(tlv->typelength); 427 tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 428 I40E_LLDP_TLV_LEN_SHIFT); 429 len = sizeof(tlv->typelength) + sizeof(ouisubtype) + 430 sizeof(struct i40e_cee_ctrl_tlv); 431 /* Return if no CEE DCBX Feature TLVs */ 432 if (tlvlen <= len) 433 return; 434 435 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len); 436 while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) { 437 typelength = ntohs(sub_tlv->hdr.typelen); 438 sublen = (u16)((typelength & 439 I40E_LLDP_TLV_LEN_MASK) >> 440 I40E_LLDP_TLV_LEN_SHIFT); 441 subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> 442 I40E_LLDP_TLV_TYPE_SHIFT); 443 switch (subtype) { 444 case I40E_CEE_SUBTYPE_PG_CFG: 445 i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); 446 break; 447 case I40E_CEE_SUBTYPE_PFC_CFG: 448 i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); 449 break; 450 case I40E_CEE_SUBTYPE_APP_PRI: 451 i40e_parse_cee_app_tlv(sub_tlv, dcbcfg); 452 break; 453 default: 454 return; /* Invalid Sub-type return */ 455 } 456 feat_tlv_count++; 457 /* Move to next sub TLV */ 458 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv + 459 sizeof(sub_tlv->hdr.typelen) + 460 sublen); 461 } 462 } 463 464 /** 465 * i40e_parse_org_tlv 466 * @tlv: Organization specific TLV 467 * @dcbcfg: Local store to update ETS REC data 468 * 469 * Currently only IEEE 802.1Qaz TLV is supported, all others 470 * will be returned 471 **/ 472 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv, 473 struct i40e_dcbx_config *dcbcfg) 474 { 475 u32 ouisubtype; 476 u32 oui; 477 478 ouisubtype = ntohl(tlv->ouisubtype); 479 oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >> 480 I40E_LLDP_TLV_OUI_SHIFT); 481 switch (oui) { 482 case I40E_IEEE_8021QAZ_OUI: 483 i40e_parse_ieee_tlv(tlv, dcbcfg); 484 break; 485 case I40E_CEE_DCBX_OUI: 486 i40e_parse_cee_tlv(tlv, dcbcfg); 487 break; 488 default: 489 break; 490 } 491 } 492 493 /** 494 * i40e_lldp_to_dcb_config 495 * @lldpmib: LLDPDU to be parsed 496 * @dcbcfg: store for LLDPDU data 497 * 498 * Parse DCB configuration from the LLDPDU 499 **/ 500 i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib, 501 struct i40e_dcbx_config *dcbcfg) 502 { 503 i40e_status ret = 0; 504 struct i40e_lldp_org_tlv *tlv; 505 u16 type; 506 u16 length; 507 u16 typelength; 508 u16 offset = 0; 509 510 if (!lldpmib || !dcbcfg) 511 return I40E_ERR_PARAM; 512 513 /* set to the start of LLDPDU */ 514 lldpmib += ETH_HLEN; 515 tlv = (struct i40e_lldp_org_tlv *)lldpmib; 516 while (1) { 517 typelength = ntohs(tlv->typelength); 518 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> 519 I40E_LLDP_TLV_TYPE_SHIFT); 520 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 521 I40E_LLDP_TLV_LEN_SHIFT); 522 offset += sizeof(typelength) + length; 523 524 /* END TLV or beyond LLDPDU size */ 525 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE)) 526 break; 527 528 switch (type) { 529 case I40E_TLV_TYPE_ORG: 530 i40e_parse_org_tlv(tlv, dcbcfg); 531 break; 532 default: 533 break; 534 } 535 536 /* Move to next TLV */ 537 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv + 538 sizeof(tlv->typelength) + 539 length); 540 } 541 542 return ret; 543 } 544 545 /** 546 * i40e_aq_get_dcb_config 547 * @hw: pointer to the hw struct 548 * @mib_type: mib type for the query 549 * @bridgetype: bridge type for the query (remote) 550 * @dcbcfg: store for LLDPDU data 551 * 552 * Query DCB configuration from the Firmware 553 **/ 554 i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type, 555 u8 bridgetype, 556 struct i40e_dcbx_config *dcbcfg) 557 { 558 i40e_status ret = 0; 559 struct i40e_virt_mem mem; 560 u8 *lldpmib; 561 562 /* Allocate the LLDPDU */ 563 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 564 if (ret) 565 return ret; 566 567 lldpmib = (u8 *)mem.va; 568 ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type, 569 (void *)lldpmib, I40E_LLDPDU_SIZE, 570 NULL, NULL, NULL); 571 if (ret) 572 goto free_mem; 573 574 /* Parse LLDP MIB to get dcb configuration */ 575 ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg); 576 577 free_mem: 578 i40e_free_virt_mem(hw, &mem); 579 return ret; 580 } 581 582 /** 583 * i40e_cee_to_dcb_v1_config 584 * @cee_cfg: pointer to CEE v1 response configuration struct 585 * @dcbcfg: DCB configuration struct 586 * 587 * Convert CEE v1 configuration from firmware to DCB configuration 588 **/ 589 static void i40e_cee_to_dcb_v1_config( 590 struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg, 591 struct i40e_dcbx_config *dcbcfg) 592 { 593 u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status); 594 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); 595 u8 i, tc, err; 596 597 /* CEE PG data to ETS config */ 598 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 599 600 /* Note that the FW creates the oper_prio_tc nibbles reversed 601 * from those in the CEE Priority Group sub-TLV. 602 */ 603 for (i = 0; i < 4; i++) { 604 tc = (u8)((cee_cfg->oper_prio_tc[i] & 605 I40E_CEE_PGID_PRIO_0_MASK) >> 606 I40E_CEE_PGID_PRIO_0_SHIFT); 607 dcbcfg->etscfg.prioritytable[i * 2] = tc; 608 tc = (u8)((cee_cfg->oper_prio_tc[i] & 609 I40E_CEE_PGID_PRIO_1_MASK) >> 610 I40E_CEE_PGID_PRIO_1_SHIFT); 611 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; 612 } 613 614 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 615 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 616 617 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 618 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { 619 /* Map it to next empty TC */ 620 dcbcfg->etscfg.prioritytable[i] = 621 cee_cfg->oper_num_tc - 1; 622 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; 623 } else { 624 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; 625 } 626 } 627 628 /* CEE PFC data to ETS config */ 629 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; 630 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 631 632 status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> 633 I40E_AQC_CEE_APP_STATUS_SHIFT; 634 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 635 /* Add APPs if Error is False */ 636 if (!err) { 637 /* CEE operating configuration supports FCoE/iSCSI/FIP only */ 638 dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; 639 640 /* FCoE APP */ 641 dcbcfg->app[0].priority = 642 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> 643 I40E_AQC_CEE_APP_FCOE_SHIFT; 644 dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; 645 dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; 646 647 /* iSCSI APP */ 648 dcbcfg->app[1].priority = 649 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> 650 I40E_AQC_CEE_APP_ISCSI_SHIFT; 651 dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; 652 dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; 653 654 /* FIP APP */ 655 dcbcfg->app[2].priority = 656 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> 657 I40E_AQC_CEE_APP_FIP_SHIFT; 658 dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; 659 dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; 660 } 661 } 662 663 /** 664 * i40e_cee_to_dcb_config 665 * @cee_cfg: pointer to CEE configuration struct 666 * @dcbcfg: DCB configuration struct 667 * 668 * Convert CEE configuration from firmware to DCB configuration 669 **/ 670 static void i40e_cee_to_dcb_config( 671 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg, 672 struct i40e_dcbx_config *dcbcfg) 673 { 674 u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); 675 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); 676 u8 i, tc, err, sync, oper; 677 678 /* CEE PG data to ETS config */ 679 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 680 681 /* Note that the FW creates the oper_prio_tc nibbles reversed 682 * from those in the CEE Priority Group sub-TLV. 683 */ 684 for (i = 0; i < 4; i++) { 685 tc = (u8)((cee_cfg->oper_prio_tc[i] & 686 I40E_CEE_PGID_PRIO_0_MASK) >> 687 I40E_CEE_PGID_PRIO_0_SHIFT); 688 dcbcfg->etscfg.prioritytable[i * 2] = tc; 689 tc = (u8)((cee_cfg->oper_prio_tc[i] & 690 I40E_CEE_PGID_PRIO_1_MASK) >> 691 I40E_CEE_PGID_PRIO_1_SHIFT); 692 dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc; 693 } 694 695 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 696 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 697 698 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 699 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { 700 /* Map it to next empty TC */ 701 dcbcfg->etscfg.prioritytable[i] = 702 cee_cfg->oper_num_tc - 1; 703 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; 704 } else { 705 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; 706 } 707 } 708 709 /* CEE PFC data to ETS config */ 710 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; 711 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 712 713 i = 0; 714 status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >> 715 I40E_AQC_CEE_FCOE_STATUS_SHIFT; 716 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 717 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 718 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 719 /* Add FCoE APP if Error is False and Oper/Sync is True */ 720 if (!err && sync && oper) { 721 /* FCoE APP */ 722 dcbcfg->app[i].priority = 723 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> 724 I40E_AQC_CEE_APP_FCOE_SHIFT; 725 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 726 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE; 727 i++; 728 } 729 730 status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >> 731 I40E_AQC_CEE_ISCSI_STATUS_SHIFT; 732 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 733 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 734 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 735 /* Add iSCSI APP if Error is False and Oper/Sync is True */ 736 if (!err && sync && oper) { 737 /* iSCSI APP */ 738 dcbcfg->app[i].priority = 739 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> 740 I40E_AQC_CEE_APP_ISCSI_SHIFT; 741 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; 742 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI; 743 i++; 744 } 745 746 status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >> 747 I40E_AQC_CEE_FIP_STATUS_SHIFT; 748 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; 749 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; 750 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; 751 /* Add FIP APP if Error is False and Oper/Sync is True */ 752 if (!err && sync && oper) { 753 /* FIP APP */ 754 dcbcfg->app[i].priority = 755 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> 756 I40E_AQC_CEE_APP_FIP_SHIFT; 757 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; 758 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP; 759 i++; 760 } 761 dcbcfg->numapps = i; 762 } 763 764 /** 765 * i40e_get_ieee_dcb_config 766 * @hw: pointer to the hw struct 767 * 768 * Get IEEE mode DCB configuration from the Firmware 769 **/ 770 static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw) 771 { 772 i40e_status ret = 0; 773 774 /* IEEE mode */ 775 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; 776 /* Get Local DCB Config */ 777 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, 778 &hw->local_dcbx_config); 779 if (ret) 780 goto out; 781 782 /* Get Remote DCB Config */ 783 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, 784 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, 785 &hw->remote_dcbx_config); 786 /* Don't treat ENOENT as an error for Remote MIBs */ 787 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 788 ret = 0; 789 790 out: 791 return ret; 792 } 793 794 /** 795 * i40e_get_dcb_config 796 * @hw: pointer to the hw struct 797 * 798 * Get DCB configuration from the Firmware 799 **/ 800 i40e_status i40e_get_dcb_config(struct i40e_hw *hw) 801 { 802 i40e_status ret = 0; 803 struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; 804 struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; 805 806 /* If Firmware version < v4.33 on X710/XL710, IEEE only */ 807 if ((hw->mac.type == I40E_MAC_XL710) && 808 (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || 809 (hw->aq.fw_maj_ver < 4))) 810 return i40e_get_ieee_dcb_config(hw); 811 812 /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */ 813 if ((hw->mac.type == I40E_MAC_XL710) && 814 ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) { 815 ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, 816 sizeof(cee_v1_cfg), NULL); 817 if (!ret) { 818 /* CEE mode */ 819 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; 820 hw->local_dcbx_config.tlv_status = 821 le16_to_cpu(cee_v1_cfg.tlv_status); 822 i40e_cee_to_dcb_v1_config(&cee_v1_cfg, 823 &hw->local_dcbx_config); 824 } 825 } else { 826 ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg, 827 sizeof(cee_cfg), NULL); 828 if (!ret) { 829 /* CEE mode */ 830 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; 831 hw->local_dcbx_config.tlv_status = 832 le32_to_cpu(cee_cfg.tlv_status); 833 i40e_cee_to_dcb_config(&cee_cfg, 834 &hw->local_dcbx_config); 835 } 836 } 837 838 /* CEE mode not enabled try querying IEEE data */ 839 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 840 return i40e_get_ieee_dcb_config(hw); 841 842 if (ret) 843 goto out; 844 845 /* Get CEE DCB Desired Config */ 846 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, 847 &hw->desired_dcbx_config); 848 if (ret) 849 goto out; 850 851 /* Get Remote DCB Config */ 852 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, 853 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, 854 &hw->remote_dcbx_config); 855 /* Don't treat ENOENT as an error for Remote MIBs */ 856 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) 857 ret = 0; 858 859 out: 860 return ret; 861 } 862 863 /** 864 * i40e_init_dcb 865 * @hw: pointer to the hw struct 866 * @enable_mib_change: enable mib change event 867 * 868 * Update DCB configuration from the Firmware 869 **/ 870 i40e_status i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change) 871 { 872 i40e_status ret = 0; 873 struct i40e_lldp_variables lldp_cfg; 874 u8 adminstatus = 0; 875 876 if (!hw->func_caps.dcb) 877 return I40E_NOT_SUPPORTED; 878 879 /* Read LLDP NVM area */ 880 if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) { 881 u8 offset = 0; 882 883 if (hw->mac.type == I40E_MAC_XL710) 884 offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET; 885 else if (hw->mac.type == I40E_MAC_X722) 886 offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET; 887 else 888 return I40E_NOT_SUPPORTED; 889 890 ret = i40e_read_nvm_module_data(hw, 891 I40E_SR_EMP_SR_SETTINGS_PTR, 892 offset, 893 I40E_LLDP_CURRENT_STATUS_OFFSET, 894 I40E_LLDP_CURRENT_STATUS_SIZE, 895 &lldp_cfg.adminstatus); 896 } else { 897 ret = i40e_read_lldp_cfg(hw, &lldp_cfg); 898 } 899 if (ret) 900 return I40E_ERR_NOT_READY; 901 902 /* Get the LLDP AdminStatus for the current port */ 903 adminstatus = lldp_cfg.adminstatus >> (hw->port * 4); 904 adminstatus &= 0xF; 905 906 /* LLDP agent disabled */ 907 if (!adminstatus) { 908 hw->dcbx_status = I40E_DCBX_STATUS_DISABLED; 909 return I40E_ERR_NOT_READY; 910 } 911 912 /* Get DCBX status */ 913 ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); 914 if (ret) 915 return ret; 916 917 /* Check the DCBX Status */ 918 if (hw->dcbx_status == I40E_DCBX_STATUS_DONE || 919 hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) { 920 /* Get current DCBX configuration */ 921 ret = i40e_get_dcb_config(hw); 922 if (ret) 923 return ret; 924 } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) { 925 return I40E_ERR_NOT_READY; 926 } 927 928 /* Configure the LLDP MIB change event */ 929 if (enable_mib_change) 930 ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL); 931 932 return ret; 933 } 934 935 /** 936 * i40e_get_fw_lldp_status 937 * @hw: pointer to the hw struct 938 * @lldp_status: pointer to the status enum 939 * 940 * Get status of FW Link Layer Discovery Protocol (LLDP) Agent. 941 * Status of agent is reported via @lldp_status parameter. 942 **/ 943 enum i40e_status_code 944 i40e_get_fw_lldp_status(struct i40e_hw *hw, 945 enum i40e_get_fw_lldp_status_resp *lldp_status) 946 { 947 struct i40e_virt_mem mem; 948 i40e_status ret; 949 u8 *lldpmib; 950 951 if (!lldp_status) 952 return I40E_ERR_PARAM; 953 954 /* Allocate buffer for the LLDPDU */ 955 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 956 if (ret) 957 return ret; 958 959 lldpmib = (u8 *)mem.va; 960 ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib, 961 I40E_LLDPDU_SIZE, NULL, NULL, NULL); 962 963 if (!ret) { 964 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED; 965 } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) { 966 /* MIB is not available yet but the agent is running */ 967 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED; 968 ret = 0; 969 } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) { 970 *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED; 971 ret = 0; 972 } 973 974 i40e_free_virt_mem(hw, &mem); 975 return ret; 976 } 977 978 /** 979 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 980 * @tlv: Fill the ETS config data in IEEE format 981 * @dcbcfg: Local store which holds the DCB Config 982 * 983 * Prepare IEEE 802.1Qaz ETS CFG TLV 984 **/ 985 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv, 986 struct i40e_dcbx_config *dcbcfg) 987 { 988 u8 priority0, priority1, maxtcwilling = 0; 989 struct i40e_dcb_ets_config *etscfg; 990 u16 offset = 0, typelength, i; 991 u8 *buf = tlv->tlvinfo; 992 u32 ouisubtype; 993 994 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 995 I40E_IEEE_ETS_TLV_LENGTH); 996 tlv->typelength = htons(typelength); 997 998 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 999 I40E_IEEE_SUBTYPE_ETS_CFG); 1000 tlv->ouisubtype = htonl(ouisubtype); 1001 1002 /* First Octet post subtype 1003 * -------------------------- 1004 * |will-|CBS | Re- | Max | 1005 * |ing | |served| TCs | 1006 * -------------------------- 1007 * |1bit | 1bit|3 bits|3bits| 1008 */ 1009 etscfg = &dcbcfg->etscfg; 1010 if (etscfg->willing) 1011 maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT); 1012 maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK; 1013 buf[offset] = maxtcwilling; 1014 1015 /* Move offset to Priority Assignment Table */ 1016 offset++; 1017 1018 /* Priority Assignment Table (4 octets) 1019 * Octets:| 1 | 2 | 3 | 4 | 1020 * ----------------------------------------- 1021 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1022 * ----------------------------------------- 1023 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1024 * ----------------------------------------- 1025 */ 1026 for (i = 0; i < 4; i++) { 1027 priority0 = etscfg->prioritytable[i * 2] & 0xF; 1028 priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF; 1029 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) | 1030 priority1; 1031 offset++; 1032 } 1033 1034 /* TC Bandwidth Table (8 octets) 1035 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1036 * --------------------------------- 1037 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1038 * --------------------------------- 1039 */ 1040 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1041 buf[offset++] = etscfg->tcbwtable[i]; 1042 1043 /* TSA Assignment Table (8 octets) 1044 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1045 * --------------------------------- 1046 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1047 * --------------------------------- 1048 */ 1049 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1050 buf[offset++] = etscfg->tsatable[i]; 1051 } 1052 1053 /** 1054 * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 1055 * @tlv: Fill ETS Recommended TLV in IEEE format 1056 * @dcbcfg: Local store which holds the DCB Config 1057 * 1058 * Prepare IEEE 802.1Qaz ETS REC TLV 1059 **/ 1060 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv, 1061 struct i40e_dcbx_config *dcbcfg) 1062 { 1063 struct i40e_dcb_ets_config *etsrec; 1064 u16 offset = 0, typelength, i; 1065 u8 priority0, priority1; 1066 u8 *buf = tlv->tlvinfo; 1067 u32 ouisubtype; 1068 1069 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1070 I40E_IEEE_ETS_TLV_LENGTH); 1071 tlv->typelength = htons(typelength); 1072 1073 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1074 I40E_IEEE_SUBTYPE_ETS_REC); 1075 tlv->ouisubtype = htonl(ouisubtype); 1076 1077 etsrec = &dcbcfg->etsrec; 1078 /* First Octet is reserved */ 1079 /* Move offset to Priority Assignment Table */ 1080 offset++; 1081 1082 /* Priority Assignment Table (4 octets) 1083 * Octets:| 1 | 2 | 3 | 4 | 1084 * ----------------------------------------- 1085 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1086 * ----------------------------------------- 1087 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1088 * ----------------------------------------- 1089 */ 1090 for (i = 0; i < 4; i++) { 1091 priority0 = etsrec->prioritytable[i * 2] & 0xF; 1092 priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF; 1093 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) | 1094 priority1; 1095 offset++; 1096 } 1097 1098 /* TC Bandwidth Table (8 octets) 1099 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1100 * --------------------------------- 1101 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1102 * --------------------------------- 1103 */ 1104 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1105 buf[offset++] = etsrec->tcbwtable[i]; 1106 1107 /* TSA Assignment Table (8 octets) 1108 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1109 * --------------------------------- 1110 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1111 * --------------------------------- 1112 */ 1113 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) 1114 buf[offset++] = etsrec->tsatable[i]; 1115 } 1116 1117 /** 1118 * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 1119 * @tlv: Fill PFC TLV in IEEE format 1120 * @dcbcfg: Local store to get PFC CFG data 1121 * 1122 * Prepare IEEE 802.1Qaz PFC CFG TLV 1123 **/ 1124 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv, 1125 struct i40e_dcbx_config *dcbcfg) 1126 { 1127 u8 *buf = tlv->tlvinfo; 1128 u32 ouisubtype; 1129 u16 typelength; 1130 1131 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1132 I40E_IEEE_PFC_TLV_LENGTH); 1133 tlv->typelength = htons(typelength); 1134 1135 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1136 I40E_IEEE_SUBTYPE_PFC_CFG); 1137 tlv->ouisubtype = htonl(ouisubtype); 1138 1139 /* ---------------------------------------- 1140 * |will-|MBC | Re- | PFC | PFC Enable | 1141 * |ing | |served| cap | | 1142 * ----------------------------------------- 1143 * |1bit | 1bit|2 bits|4bits| 1 octet | 1144 */ 1145 if (dcbcfg->pfc.willing) 1146 buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT); 1147 1148 if (dcbcfg->pfc.mbc) 1149 buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT); 1150 1151 buf[0] |= dcbcfg->pfc.pfccap & 0xF; 1152 buf[1] = dcbcfg->pfc.pfcenable; 1153 } 1154 1155 /** 1156 * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 1157 * @tlv: Fill APP TLV in IEEE format 1158 * @dcbcfg: Local store to get APP CFG data 1159 * 1160 * Prepare IEEE 802.1Qaz APP CFG TLV 1161 **/ 1162 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv, 1163 struct i40e_dcbx_config *dcbcfg) 1164 { 1165 u16 typelength, length, offset = 0; 1166 u8 priority, selector, i = 0; 1167 u8 *buf = tlv->tlvinfo; 1168 u32 ouisubtype; 1169 1170 /* No APP TLVs then just return */ 1171 if (dcbcfg->numapps == 0) 1172 return; 1173 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) | 1174 I40E_IEEE_SUBTYPE_APP_PRI); 1175 tlv->ouisubtype = htonl(ouisubtype); 1176 1177 /* Move offset to App Priority Table */ 1178 offset++; 1179 /* Application Priority Table (3 octets) 1180 * Octets:| 1 | 2 | 3 | 1181 * ----------------------------------------- 1182 * |Priority|Rsrvd| Sel | Protocol ID | 1183 * ----------------------------------------- 1184 * Bits:|23 21|20 19|18 16|15 0| 1185 * ----------------------------------------- 1186 */ 1187 while (i < dcbcfg->numapps) { 1188 priority = dcbcfg->app[i].priority & 0x7; 1189 selector = dcbcfg->app[i].selector & 0x7; 1190 buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector; 1191 buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF; 1192 buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF; 1193 /* Move to next app */ 1194 offset += 3; 1195 i++; 1196 if (i >= I40E_DCBX_MAX_APPS) 1197 break; 1198 } 1199 /* length includes size of ouisubtype + 1 reserved + 3*numapps */ 1200 length = sizeof(tlv->ouisubtype) + 1 + (i * 3); 1201 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) | 1202 (length & 0x1FF)); 1203 tlv->typelength = htons(typelength); 1204 } 1205 1206 /** 1207 * i40e_add_dcb_tlv - Add all IEEE TLVs 1208 * @tlv: pointer to org tlv 1209 * @dcbcfg: pointer to modified dcbx config structure * 1210 * @tlvid: tlv id to be added 1211 * add tlv information 1212 **/ 1213 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv, 1214 struct i40e_dcbx_config *dcbcfg, 1215 u16 tlvid) 1216 { 1217 switch (tlvid) { 1218 case I40E_IEEE_TLV_ID_ETS_CFG: 1219 i40e_add_ieee_ets_tlv(tlv, dcbcfg); 1220 break; 1221 case I40E_IEEE_TLV_ID_ETS_REC: 1222 i40e_add_ieee_etsrec_tlv(tlv, dcbcfg); 1223 break; 1224 case I40E_IEEE_TLV_ID_PFC_CFG: 1225 i40e_add_ieee_pfc_tlv(tlv, dcbcfg); 1226 break; 1227 case I40E_IEEE_TLV_ID_APP_PRI: 1228 i40e_add_ieee_app_pri_tlv(tlv, dcbcfg); 1229 break; 1230 default: 1231 break; 1232 } 1233 } 1234 1235 /** 1236 * i40e_set_dcb_config - Set the local LLDP MIB to FW 1237 * @hw: pointer to the hw struct 1238 * 1239 * Set DCB configuration to the Firmware 1240 **/ 1241 i40e_status i40e_set_dcb_config(struct i40e_hw *hw) 1242 { 1243 struct i40e_dcbx_config *dcbcfg; 1244 struct i40e_virt_mem mem; 1245 u8 mib_type, *lldpmib; 1246 i40e_status ret; 1247 u16 miblen; 1248 1249 /* update the hw local config */ 1250 dcbcfg = &hw->local_dcbx_config; 1251 /* Allocate the LLDPDU */ 1252 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); 1253 if (ret) 1254 return ret; 1255 1256 mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB; 1257 if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) { 1258 mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS << 1259 SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT; 1260 } 1261 lldpmib = (u8 *)mem.va; 1262 i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg); 1263 ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL); 1264 1265 i40e_free_virt_mem(hw, &mem); 1266 return ret; 1267 } 1268 1269 /** 1270 * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format 1271 * @lldpmib: pointer to mib to be output 1272 * @miblen: pointer to u16 for length of lldpmib 1273 * @dcbcfg: store for LLDPDU data 1274 * 1275 * send DCB configuration to FW 1276 **/ 1277 i40e_status i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen, 1278 struct i40e_dcbx_config *dcbcfg) 1279 { 1280 u16 length, offset = 0, tlvid, typelength; 1281 struct i40e_lldp_org_tlv *tlv; 1282 1283 tlv = (struct i40e_lldp_org_tlv *)lldpmib; 1284 tlvid = I40E_TLV_ID_START; 1285 do { 1286 i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++); 1287 typelength = ntohs(tlv->typelength); 1288 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> 1289 I40E_LLDP_TLV_LEN_SHIFT); 1290 if (length) 1291 offset += length + I40E_IEEE_TLV_HEADER_LENGTH; 1292 /* END TLV or beyond LLDPDU size */ 1293 if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU || 1294 offset >= I40E_LLDPDU_SIZE) 1295 break; 1296 /* Move to next TLV */ 1297 if (length) 1298 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv + 1299 sizeof(tlv->typelength) + length); 1300 } while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU); 1301 *miblen = offset; 1302 return I40E_SUCCESS; 1303 } 1304 1305 /** 1306 * i40e_dcb_hw_rx_fifo_config 1307 * @hw: pointer to the hw struct 1308 * @ets_mode: Strict Priority or Round Robin mode 1309 * @non_ets_mode: Strict Priority or Round Robin 1310 * @max_exponent: Exponent to calculate max refill credits 1311 * @lltc_map: Low latency TC bitmap 1312 * 1313 * Configure HW Rx FIFO as part of DCB configuration. 1314 **/ 1315 void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw, 1316 enum i40e_dcb_arbiter_mode ets_mode, 1317 enum i40e_dcb_arbiter_mode non_ets_mode, 1318 u32 max_exponent, 1319 u8 lltc_map) 1320 { 1321 u32 reg = rd32(hw, I40E_PRTDCB_RETSC); 1322 1323 reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK; 1324 reg |= ((u32)ets_mode << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) & 1325 I40E_PRTDCB_RETSC_ETS_MODE_MASK; 1326 1327 reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK; 1328 reg |= ((u32)non_ets_mode << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) & 1329 I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK; 1330 1331 reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK; 1332 reg |= (max_exponent << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) & 1333 I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK; 1334 1335 reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK; 1336 reg |= (lltc_map << I40E_PRTDCB_RETSC_LLTC_SHIFT) & 1337 I40E_PRTDCB_RETSC_LLTC_MASK; 1338 wr32(hw, I40E_PRTDCB_RETSC, reg); 1339 } 1340 1341 /** 1342 * i40e_dcb_hw_rx_cmd_monitor_config 1343 * @hw: pointer to the hw struct 1344 * @num_tc: Total number of traffic class 1345 * @num_ports: Total number of ports on device 1346 * 1347 * Configure HW Rx command monitor as part of DCB configuration. 1348 **/ 1349 void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw, 1350 u8 num_tc, u8 num_ports) 1351 { 1352 u32 threshold; 1353 u32 fifo_size; 1354 u32 reg; 1355 1356 /* Set the threshold and fifo_size based on number of ports */ 1357 switch (num_ports) { 1358 case 1: 1359 threshold = I40E_DCB_1_PORT_THRESHOLD; 1360 fifo_size = I40E_DCB_1_PORT_FIFO_SIZE; 1361 break; 1362 case 2: 1363 if (num_tc > 4) { 1364 threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC; 1365 fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC; 1366 } else { 1367 threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC; 1368 fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC; 1369 } 1370 break; 1371 case 4: 1372 if (num_tc > 4) { 1373 threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC; 1374 fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC; 1375 } else { 1376 threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC; 1377 fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC; 1378 } 1379 break; 1380 default: 1381 i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n", 1382 (u32)num_ports); 1383 return; 1384 } 1385 1386 /* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR 1387 * based on the number of ports and traffic classes for a given port as 1388 * part of DCB configuration. 1389 */ 1390 reg = rd32(hw, I40E_PRT_SWR_PM_THR); 1391 reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK; 1392 reg |= (threshold << I40E_PRT_SWR_PM_THR_THRESHOLD_SHIFT) & 1393 I40E_PRT_SWR_PM_THR_THRESHOLD_MASK; 1394 wr32(hw, I40E_PRT_SWR_PM_THR, reg); 1395 1396 reg = rd32(hw, I40E_PRTDCB_RPPMC); 1397 reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK; 1398 reg |= (fifo_size << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) & 1399 I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK; 1400 wr32(hw, I40E_PRTDCB_RPPMC, reg); 1401 } 1402 1403 /** 1404 * i40e_dcb_hw_pfc_config 1405 * @hw: pointer to the hw struct 1406 * @pfc_en: Bitmap of PFC enabled priorities 1407 * @prio_tc: priority to tc assignment indexed by priority 1408 * 1409 * Configure HW Priority Flow Controller as part of DCB configuration. 1410 **/ 1411 void i40e_dcb_hw_pfc_config(struct i40e_hw *hw, 1412 u8 pfc_en, u8 *prio_tc) 1413 { 1414 u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2; 1415 u32 link_speed = hw->phy.link_info.link_speed; 1416 u8 first_pfc_prio = 0; 1417 u8 num_pfc_tc = 0; 1418 u8 tc2pfc = 0; 1419 u32 reg; 1420 u8 i; 1421 1422 /* Get Number of PFC TCs and TC2PFC map */ 1423 for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { 1424 if (pfc_en & BIT(i)) { 1425 if (!first_pfc_prio) 1426 first_pfc_prio = i; 1427 /* Set bit for the PFC TC */ 1428 tc2pfc |= BIT(prio_tc[i]); 1429 num_pfc_tc++; 1430 } 1431 } 1432 1433 switch (link_speed) { 1434 case I40E_LINK_SPEED_10GB: 1435 reg = rd32(hw, I40E_PRTDCB_MFLCN); 1436 reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) & 1437 I40E_PRTDCB_MFLCN_DPF_MASK; 1438 reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK; 1439 reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK; 1440 if (pfc_en) { 1441 reg |= BIT(I40E_PRTDCB_MFLCN_RPFCM_SHIFT) & 1442 I40E_PRTDCB_MFLCN_RPFCM_MASK; 1443 reg |= ((u32)pfc_en << I40E_PRTDCB_MFLCN_RPFCE_SHIFT) & 1444 I40E_PRTDCB_MFLCN_RPFCE_MASK; 1445 } 1446 wr32(hw, I40E_PRTDCB_MFLCN, reg); 1447 1448 reg = rd32(hw, I40E_PRTDCB_FCCFG); 1449 reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK; 1450 if (pfc_en) 1451 reg |= (I40E_DCB_PFC_ENABLED << 1452 I40E_PRTDCB_FCCFG_TFCE_SHIFT) & 1453 I40E_PRTDCB_FCCFG_TFCE_MASK; 1454 wr32(hw, I40E_PRTDCB_FCCFG, reg); 1455 1456 /* FCTTV and FCRTV to be set by default */ 1457 break; 1458 case I40E_LINK_SPEED_40GB: 1459 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP); 1460 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK; 1461 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg); 1462 1463 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP); 1464 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK; 1465 reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) & 1466 I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK; 1467 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg); 1468 1469 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE); 1470 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK; 1471 reg |= ((u32)pfc_en << 1472 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) & 1473 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK; 1474 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg); 1475 1476 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE); 1477 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK; 1478 reg |= ((u32)pfc_en << 1479 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) & 1480 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK; 1481 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg); 1482 1483 for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) { 1484 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i)); 1485 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK; 1486 if (pfc_en) { 1487 reg |= ((u32)refresh_time << 1488 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) & 1489 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK; 1490 } 1491 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg); 1492 } 1493 /* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF 1494 * for all user priorities 1495 */ 1496 break; 1497 } 1498 1499 reg = rd32(hw, I40E_PRTDCB_TC2PFC); 1500 reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK; 1501 reg |= ((u32)tc2pfc << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) & 1502 I40E_PRTDCB_TC2PFC_TC2PFC_MASK; 1503 wr32(hw, I40E_PRTDCB_TC2PFC, reg); 1504 1505 reg = rd32(hw, I40E_PRTDCB_RUP); 1506 reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK; 1507 reg |= ((u32)first_pfc_prio << I40E_PRTDCB_RUP_NOVLANUP_SHIFT) & 1508 I40E_PRTDCB_RUP_NOVLANUP_MASK; 1509 wr32(hw, I40E_PRTDCB_RUP, reg); 1510 1511 reg = rd32(hw, I40E_PRTDCB_TDPMC); 1512 reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK; 1513 if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) { 1514 reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) & 1515 I40E_PRTDCB_TDPMC_TCPM_MODE_MASK; 1516 } 1517 wr32(hw, I40E_PRTDCB_TDPMC, reg); 1518 1519 reg = rd32(hw, I40E_PRTDCB_TCPMC); 1520 reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK; 1521 if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) { 1522 reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) & 1523 I40E_PRTDCB_TCPMC_TCPM_MODE_MASK; 1524 } 1525 wr32(hw, I40E_PRTDCB_TCPMC, reg); 1526 } 1527 1528 /** 1529 * i40e_dcb_hw_set_num_tc 1530 * @hw: pointer to the hw struct 1531 * @num_tc: number of traffic classes 1532 * 1533 * Configure number of traffic classes in HW 1534 **/ 1535 void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc) 1536 { 1537 u32 reg = rd32(hw, I40E_PRTDCB_GENC); 1538 1539 reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK; 1540 reg |= ((u32)num_tc << I40E_PRTDCB_GENC_NUMTC_SHIFT) & 1541 I40E_PRTDCB_GENC_NUMTC_MASK; 1542 wr32(hw, I40E_PRTDCB_GENC, reg); 1543 } 1544 1545 /** 1546 * i40e_dcb_hw_get_num_tc 1547 * @hw: pointer to the hw struct 1548 * 1549 * Returns number of traffic classes configured in HW 1550 **/ 1551 u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw) 1552 { 1553 u32 reg = rd32(hw, I40E_PRTDCB_GENC); 1554 1555 return (u8)((reg & I40E_PRTDCB_GENC_NUMTC_MASK) >> 1556 I40E_PRTDCB_GENC_NUMTC_SHIFT); 1557 } 1558 1559 /** 1560 * i40e_dcb_hw_rx_ets_bw_config 1561 * @hw: pointer to the hw struct 1562 * @bw_share: Bandwidth share indexed per traffic class 1563 * @mode: Strict Priority or Round Robin mode between UP sharing same 1564 * traffic class 1565 * @prio_type: TC is ETS enabled or strict priority 1566 * 1567 * Configure HW Rx ETS bandwidth as part of DCB configuration. 1568 **/ 1569 void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share, 1570 u8 *mode, u8 *prio_type) 1571 { 1572 u32 reg; 1573 u8 i; 1574 1575 for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) { 1576 reg = rd32(hw, I40E_PRTDCB_RETSTCC(i)); 1577 reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK | 1578 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK | 1579 I40E_PRTDCB_RETSTCC_ETSTC_SHIFT); 1580 reg |= ((u32)bw_share[i] << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) & 1581 I40E_PRTDCB_RETSTCC_BWSHARE_MASK; 1582 reg |= ((u32)mode[i] << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) & 1583 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK; 1584 reg |= ((u32)prio_type[i] << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) & 1585 I40E_PRTDCB_RETSTCC_ETSTC_MASK; 1586 wr32(hw, I40E_PRTDCB_RETSTCC(i), reg); 1587 } 1588 } 1589 1590 /** 1591 * i40e_dcb_hw_rx_ets_bw_config 1592 * @hw: pointer to the hw struct 1593 * @prio_tc: priority to tc assignment indexed by priority 1594 * 1595 * Configure HW Rx UP2TC map as part of DCB configuration. 1596 **/ 1597 void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc) 1598 { 1599 u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC); 1600 #define I40E_UP2TC_REG(val, i) \ 1601 (((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \ 1602 I40E_PRTDCB_RUP2TC_UP##i##TC_MASK) 1603 1604 reg |= I40E_UP2TC_REG(prio_tc[0], 0); 1605 reg |= I40E_UP2TC_REG(prio_tc[1], 1); 1606 reg |= I40E_UP2TC_REG(prio_tc[2], 2); 1607 reg |= I40E_UP2TC_REG(prio_tc[3], 3); 1608 reg |= I40E_UP2TC_REG(prio_tc[4], 4); 1609 reg |= I40E_UP2TC_REG(prio_tc[5], 5); 1610 reg |= I40E_UP2TC_REG(prio_tc[6], 6); 1611 reg |= I40E_UP2TC_REG(prio_tc[7], 7); 1612 1613 wr32(hw, I40E_PRTDCB_RUP2TC, reg); 1614 } 1615 1616 /** 1617 * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes 1618 * @hw: pointer to the hw struct 1619 * @num_ports: Number of available ports on the device 1620 * @eee_enabled: EEE enabled for the given port 1621 * @pfc_en: Bit map of PFC enabled traffic classes 1622 * @mfs_tc: Array of max frame size for each traffic class 1623 * @pb_cfg: pointer to packet buffer configuration 1624 * 1625 * Calculate the shared and dedicated per TC pool sizes, 1626 * watermarks and threshold values. 1627 **/ 1628 void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw, 1629 u8 num_ports, bool eee_enabled, 1630 u8 pfc_en, u32 *mfs_tc, 1631 struct i40e_rx_pb_config *pb_cfg) 1632 { 1633 u32 pool_size[I40E_MAX_TRAFFIC_CLASS]; 1634 u32 high_wm[I40E_MAX_TRAFFIC_CLASS]; 1635 u32 low_wm[I40E_MAX_TRAFFIC_CLASS]; 1636 u32 total_pool_size = 0; 1637 int shared_pool_size; /* Need signed variable */ 1638 u32 port_pb_size; 1639 u32 mfs_max = 0; 1640 u32 pcirtt; 1641 u8 i; 1642 1643 /* Get the MFS(max) for the port */ 1644 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1645 if (mfs_tc[i] > mfs_max) 1646 mfs_max = mfs_tc[i]; 1647 } 1648 1649 pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G); 1650 1651 /* Calculate effective Rx PB size per port */ 1652 port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports; 1653 if (eee_enabled) 1654 port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME); 1655 port_pb_size -= mfs_max; 1656 1657 /* Step 1 Calculating tc pool/shared pool sizes and watermarks */ 1658 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1659 if (pfc_en & BIT(i)) { 1660 low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR * 1661 mfs_tc[i]) + pcirtt; 1662 high_wm[i] = low_wm[i]; 1663 high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE) 1664 ? mfs_max : I40E_MAX_FRAME_SIZE); 1665 pool_size[i] = high_wm[i]; 1666 pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max, 1667 mfs_tc[i])); 1668 } else { 1669 low_wm[i] = 0; 1670 pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR * 1671 mfs_tc[i]) + pcirtt; 1672 high_wm[i] = pool_size[i]; 1673 } 1674 total_pool_size += pool_size[i]; 1675 } 1676 1677 shared_pool_size = port_pb_size - total_pool_size; 1678 if (shared_pool_size > 0) { 1679 pb_cfg->shared_pool_size = shared_pool_size; 1680 pb_cfg->shared_pool_high_wm = shared_pool_size; 1681 pb_cfg->shared_pool_low_wm = 0; 1682 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1683 pb_cfg->shared_pool_low_thresh[i] = 0; 1684 pb_cfg->shared_pool_high_thresh[i] = shared_pool_size; 1685 pb_cfg->tc_pool_size[i] = pool_size[i]; 1686 pb_cfg->tc_pool_high_wm[i] = high_wm[i]; 1687 pb_cfg->tc_pool_low_wm[i] = low_wm[i]; 1688 } 1689 1690 } else { 1691 i40e_debug(hw, I40E_DEBUG_DCB, 1692 "The shared pool size for the port is negative %d.\n", 1693 shared_pool_size); 1694 } 1695 } 1696 1697 /** 1698 * i40e_dcb_hw_rx_pb_config 1699 * @hw: pointer to the hw struct 1700 * @old_pb_cfg: Existing Rx Packet buffer configuration 1701 * @new_pb_cfg: New Rx Packet buffer configuration 1702 * 1703 * Program the Rx Packet Buffer registers. 1704 **/ 1705 void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw, 1706 struct i40e_rx_pb_config *old_pb_cfg, 1707 struct i40e_rx_pb_config *new_pb_cfg) 1708 { 1709 u32 old_val; 1710 u32 new_val; 1711 u32 reg; 1712 u8 i; 1713 1714 /* The Rx Packet buffer register programming needs to be done in a 1715 * certain order and the following code is based on that 1716 * requirement. 1717 */ 1718 1719 /* Program the shared pool low water mark per port if decreasing */ 1720 old_val = old_pb_cfg->shared_pool_low_wm; 1721 new_val = new_pb_cfg->shared_pool_low_wm; 1722 if (new_val < old_val) { 1723 reg = rd32(hw, I40E_PRTRPB_SLW); 1724 reg &= ~I40E_PRTRPB_SLW_SLW_MASK; 1725 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) & 1726 I40E_PRTRPB_SLW_SLW_MASK; 1727 wr32(hw, I40E_PRTRPB_SLW, reg); 1728 } 1729 1730 /* Program the shared pool low threshold and tc pool 1731 * low water mark per TC that are decreasing. 1732 */ 1733 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1734 old_val = old_pb_cfg->shared_pool_low_thresh[i]; 1735 new_val = new_pb_cfg->shared_pool_low_thresh[i]; 1736 if (new_val < old_val) { 1737 reg = rd32(hw, I40E_PRTRPB_SLT(i)); 1738 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK; 1739 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) & 1740 I40E_PRTRPB_SLT_SLT_TCN_MASK; 1741 wr32(hw, I40E_PRTRPB_SLT(i), reg); 1742 } 1743 1744 old_val = old_pb_cfg->tc_pool_low_wm[i]; 1745 new_val = new_pb_cfg->tc_pool_low_wm[i]; 1746 if (new_val < old_val) { 1747 reg = rd32(hw, I40E_PRTRPB_DLW(i)); 1748 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK; 1749 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) & 1750 I40E_PRTRPB_DLW_DLW_TCN_MASK; 1751 wr32(hw, I40E_PRTRPB_DLW(i), reg); 1752 } 1753 } 1754 1755 /* Program the shared pool high water mark per port if decreasing */ 1756 old_val = old_pb_cfg->shared_pool_high_wm; 1757 new_val = new_pb_cfg->shared_pool_high_wm; 1758 if (new_val < old_val) { 1759 reg = rd32(hw, I40E_PRTRPB_SHW); 1760 reg &= ~I40E_PRTRPB_SHW_SHW_MASK; 1761 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) & 1762 I40E_PRTRPB_SHW_SHW_MASK; 1763 wr32(hw, I40E_PRTRPB_SHW, reg); 1764 } 1765 1766 /* Program the shared pool high threshold and tc pool 1767 * high water mark per TC that are decreasing. 1768 */ 1769 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1770 old_val = old_pb_cfg->shared_pool_high_thresh[i]; 1771 new_val = new_pb_cfg->shared_pool_high_thresh[i]; 1772 if (new_val < old_val) { 1773 reg = rd32(hw, I40E_PRTRPB_SHT(i)); 1774 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK; 1775 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) & 1776 I40E_PRTRPB_SHT_SHT_TCN_MASK; 1777 wr32(hw, I40E_PRTRPB_SHT(i), reg); 1778 } 1779 1780 old_val = old_pb_cfg->tc_pool_high_wm[i]; 1781 new_val = new_pb_cfg->tc_pool_high_wm[i]; 1782 if (new_val < old_val) { 1783 reg = rd32(hw, I40E_PRTRPB_DHW(i)); 1784 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK; 1785 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) & 1786 I40E_PRTRPB_DHW_DHW_TCN_MASK; 1787 wr32(hw, I40E_PRTRPB_DHW(i), reg); 1788 } 1789 } 1790 1791 /* Write Dedicated Pool Sizes per TC */ 1792 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1793 new_val = new_pb_cfg->tc_pool_size[i]; 1794 reg = rd32(hw, I40E_PRTRPB_DPS(i)); 1795 reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK; 1796 reg |= (new_val << I40E_PRTRPB_DPS_DPS_TCN_SHIFT) & 1797 I40E_PRTRPB_DPS_DPS_TCN_MASK; 1798 wr32(hw, I40E_PRTRPB_DPS(i), reg); 1799 } 1800 1801 /* Write Shared Pool Size per port */ 1802 new_val = new_pb_cfg->shared_pool_size; 1803 reg = rd32(hw, I40E_PRTRPB_SPS); 1804 reg &= ~I40E_PRTRPB_SPS_SPS_MASK; 1805 reg |= (new_val << I40E_PRTRPB_SPS_SPS_SHIFT) & 1806 I40E_PRTRPB_SPS_SPS_MASK; 1807 wr32(hw, I40E_PRTRPB_SPS, reg); 1808 1809 /* Program the shared pool low water mark per port if increasing */ 1810 old_val = old_pb_cfg->shared_pool_low_wm; 1811 new_val = new_pb_cfg->shared_pool_low_wm; 1812 if (new_val > old_val) { 1813 reg = rd32(hw, I40E_PRTRPB_SLW); 1814 reg &= ~I40E_PRTRPB_SLW_SLW_MASK; 1815 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) & 1816 I40E_PRTRPB_SLW_SLW_MASK; 1817 wr32(hw, I40E_PRTRPB_SLW, reg); 1818 } 1819 1820 /* Program the shared pool low threshold and tc pool 1821 * low water mark per TC that are increasing. 1822 */ 1823 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1824 old_val = old_pb_cfg->shared_pool_low_thresh[i]; 1825 new_val = new_pb_cfg->shared_pool_low_thresh[i]; 1826 if (new_val > old_val) { 1827 reg = rd32(hw, I40E_PRTRPB_SLT(i)); 1828 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK; 1829 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) & 1830 I40E_PRTRPB_SLT_SLT_TCN_MASK; 1831 wr32(hw, I40E_PRTRPB_SLT(i), reg); 1832 } 1833 1834 old_val = old_pb_cfg->tc_pool_low_wm[i]; 1835 new_val = new_pb_cfg->tc_pool_low_wm[i]; 1836 if (new_val > old_val) { 1837 reg = rd32(hw, I40E_PRTRPB_DLW(i)); 1838 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK; 1839 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) & 1840 I40E_PRTRPB_DLW_DLW_TCN_MASK; 1841 wr32(hw, I40E_PRTRPB_DLW(i), reg); 1842 } 1843 } 1844 1845 /* Program the shared pool high water mark per port if increasing */ 1846 old_val = old_pb_cfg->shared_pool_high_wm; 1847 new_val = new_pb_cfg->shared_pool_high_wm; 1848 if (new_val > old_val) { 1849 reg = rd32(hw, I40E_PRTRPB_SHW); 1850 reg &= ~I40E_PRTRPB_SHW_SHW_MASK; 1851 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) & 1852 I40E_PRTRPB_SHW_SHW_MASK; 1853 wr32(hw, I40E_PRTRPB_SHW, reg); 1854 } 1855 1856 /* Program the shared pool high threshold and tc pool 1857 * high water mark per TC that are increasing. 1858 */ 1859 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1860 old_val = old_pb_cfg->shared_pool_high_thresh[i]; 1861 new_val = new_pb_cfg->shared_pool_high_thresh[i]; 1862 if (new_val > old_val) { 1863 reg = rd32(hw, I40E_PRTRPB_SHT(i)); 1864 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK; 1865 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) & 1866 I40E_PRTRPB_SHT_SHT_TCN_MASK; 1867 wr32(hw, I40E_PRTRPB_SHT(i), reg); 1868 } 1869 1870 old_val = old_pb_cfg->tc_pool_high_wm[i]; 1871 new_val = new_pb_cfg->tc_pool_high_wm[i]; 1872 if (new_val > old_val) { 1873 reg = rd32(hw, I40E_PRTRPB_DHW(i)); 1874 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK; 1875 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) & 1876 I40E_PRTRPB_DHW_DHW_TCN_MASK; 1877 wr32(hw, I40E_PRTRPB_DHW(i), reg); 1878 } 1879 } 1880 } 1881 1882 /** 1883 * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM 1884 * @hw: pointer to the HW structure 1885 * @lldp_cfg: pointer to hold lldp configuration variables 1886 * @module: address of the module pointer 1887 * @word_offset: offset of LLDP configuration 1888 * 1889 * Reads the LLDP configuration data from NVM using passed addresses 1890 **/ 1891 static i40e_status _i40e_read_lldp_cfg(struct i40e_hw *hw, 1892 struct i40e_lldp_variables *lldp_cfg, 1893 u8 module, u32 word_offset) 1894 { 1895 u32 address, offset = (2 * word_offset); 1896 i40e_status ret; 1897 __le16 raw_mem; 1898 u16 mem; 1899 1900 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1901 if (ret) 1902 return ret; 1903 1904 ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem, 1905 true, NULL); 1906 i40e_release_nvm(hw); 1907 if (ret) 1908 return ret; 1909 1910 mem = le16_to_cpu(raw_mem); 1911 /* Check if this pointer needs to be read in word size or 4K sector 1912 * units. 1913 */ 1914 if (mem & I40E_PTR_TYPE) 1915 address = (0x7FFF & mem) * 4096; 1916 else 1917 address = (0x7FFF & mem) * 2; 1918 1919 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1920 if (ret) 1921 goto err_lldp_cfg; 1922 1923 ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem, 1924 true, NULL); 1925 i40e_release_nvm(hw); 1926 if (ret) 1927 return ret; 1928 1929 mem = le16_to_cpu(raw_mem); 1930 offset = mem + word_offset; 1931 offset *= 2; 1932 1933 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1934 if (ret) 1935 goto err_lldp_cfg; 1936 1937 ret = i40e_aq_read_nvm(hw, 0, address + offset, 1938 sizeof(struct i40e_lldp_variables), lldp_cfg, 1939 true, NULL); 1940 i40e_release_nvm(hw); 1941 1942 err_lldp_cfg: 1943 return ret; 1944 } 1945 1946 /** 1947 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM 1948 * @hw: pointer to the HW structure 1949 * @lldp_cfg: pointer to hold lldp configuration variables 1950 * 1951 * Reads the LLDP configuration data from NVM 1952 **/ 1953 i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw, 1954 struct i40e_lldp_variables *lldp_cfg) 1955 { 1956 i40e_status ret = 0; 1957 u32 mem; 1958 1959 if (!lldp_cfg) 1960 return I40E_ERR_PARAM; 1961 1962 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1963 if (ret) 1964 return ret; 1965 1966 ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem), 1967 &mem, true, NULL); 1968 i40e_release_nvm(hw); 1969 if (ret) 1970 return ret; 1971 1972 /* Read a bit that holds information whether we are running flat or 1973 * structured NVM image. Flat image has LLDP configuration in shadow 1974 * ram, so there is a need to pass different addresses for both cases. 1975 */ 1976 if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) { 1977 /* Flat NVM case */ 1978 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR, 1979 I40E_SR_LLDP_CFG_PTR); 1980 } else { 1981 /* Good old structured NVM image */ 1982 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR, 1983 I40E_NVM_LLDP_CFG_PTR); 1984 } 1985 1986 return ret; 1987 } 1988