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