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_rx_ets_bw_config 1495 * @hw: pointer to the hw struct 1496 * @bw_share: Bandwidth share indexed per traffic class 1497 * @mode: Strict Priority or Round Robin mode between UP sharing same 1498 * traffic class 1499 * @prio_type: TC is ETS enabled or strict priority 1500 * 1501 * Configure HW Rx ETS bandwidth as part of DCB configuration. 1502 **/ 1503 void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share, 1504 u8 *mode, u8 *prio_type) 1505 { 1506 u32 reg; 1507 u8 i; 1508 1509 for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) { 1510 reg = rd32(hw, I40E_PRTDCB_RETSTCC(i)); 1511 reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK | 1512 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK | 1513 I40E_PRTDCB_RETSTCC_ETSTC_MASK); 1514 reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_BWSHARE_MASK, 1515 bw_share[i]); 1516 reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK, 1517 mode[i]); 1518 reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_ETSTC_MASK, 1519 prio_type[i]); 1520 wr32(hw, I40E_PRTDCB_RETSTCC(i), reg); 1521 } 1522 } 1523 1524 /** 1525 * i40e_dcb_hw_rx_up2tc_config 1526 * @hw: pointer to the hw struct 1527 * @prio_tc: priority to tc assignment indexed by priority 1528 * 1529 * Configure HW Rx UP2TC map as part of DCB configuration. 1530 **/ 1531 void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc) 1532 { 1533 u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC); 1534 #define I40E_UP2TC_REG(val, i) \ 1535 (((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \ 1536 I40E_PRTDCB_RUP2TC_UP##i##TC_MASK) 1537 1538 reg |= I40E_UP2TC_REG(prio_tc[0], 0); 1539 reg |= I40E_UP2TC_REG(prio_tc[1], 1); 1540 reg |= I40E_UP2TC_REG(prio_tc[2], 2); 1541 reg |= I40E_UP2TC_REG(prio_tc[3], 3); 1542 reg |= I40E_UP2TC_REG(prio_tc[4], 4); 1543 reg |= I40E_UP2TC_REG(prio_tc[5], 5); 1544 reg |= I40E_UP2TC_REG(prio_tc[6], 6); 1545 reg |= I40E_UP2TC_REG(prio_tc[7], 7); 1546 1547 wr32(hw, I40E_PRTDCB_RUP2TC, reg); 1548 } 1549 1550 /** 1551 * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes 1552 * @hw: pointer to the hw struct 1553 * @num_ports: Number of available ports on the device 1554 * @eee_enabled: EEE enabled for the given port 1555 * @pfc_en: Bit map of PFC enabled traffic classes 1556 * @mfs_tc: Array of max frame size for each traffic class 1557 * @pb_cfg: pointer to packet buffer configuration 1558 * 1559 * Calculate the shared and dedicated per TC pool sizes, 1560 * watermarks and threshold values. 1561 **/ 1562 void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw, 1563 u8 num_ports, bool eee_enabled, 1564 u8 pfc_en, u32 *mfs_tc, 1565 struct i40e_rx_pb_config *pb_cfg) 1566 { 1567 u32 pool_size[I40E_MAX_TRAFFIC_CLASS]; 1568 u32 high_wm[I40E_MAX_TRAFFIC_CLASS]; 1569 u32 low_wm[I40E_MAX_TRAFFIC_CLASS]; 1570 u32 total_pool_size = 0; 1571 int shared_pool_size; /* Need signed variable */ 1572 u32 port_pb_size; 1573 u32 mfs_max = 0; 1574 u32 pcirtt; 1575 u8 i; 1576 1577 /* Get the MFS(max) for the port */ 1578 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1579 if (mfs_tc[i] > mfs_max) 1580 mfs_max = mfs_tc[i]; 1581 } 1582 1583 pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G); 1584 1585 /* Calculate effective Rx PB size per port */ 1586 port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports; 1587 if (eee_enabled) 1588 port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME); 1589 port_pb_size -= mfs_max; 1590 1591 /* Step 1 Calculating tc pool/shared pool sizes and watermarks */ 1592 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1593 if (pfc_en & BIT(i)) { 1594 low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR * 1595 mfs_tc[i]) + pcirtt; 1596 high_wm[i] = low_wm[i]; 1597 high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE) 1598 ? mfs_max : I40E_MAX_FRAME_SIZE); 1599 pool_size[i] = high_wm[i]; 1600 pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max, 1601 mfs_tc[i])); 1602 } else { 1603 low_wm[i] = 0; 1604 pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR * 1605 mfs_tc[i]) + pcirtt; 1606 high_wm[i] = pool_size[i]; 1607 } 1608 total_pool_size += pool_size[i]; 1609 } 1610 1611 shared_pool_size = port_pb_size - total_pool_size; 1612 if (shared_pool_size > 0) { 1613 pb_cfg->shared_pool_size = shared_pool_size; 1614 pb_cfg->shared_pool_high_wm = shared_pool_size; 1615 pb_cfg->shared_pool_low_wm = 0; 1616 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1617 pb_cfg->shared_pool_low_thresh[i] = 0; 1618 pb_cfg->shared_pool_high_thresh[i] = shared_pool_size; 1619 pb_cfg->tc_pool_size[i] = pool_size[i]; 1620 pb_cfg->tc_pool_high_wm[i] = high_wm[i]; 1621 pb_cfg->tc_pool_low_wm[i] = low_wm[i]; 1622 } 1623 1624 } else { 1625 i40e_debug(hw, I40E_DEBUG_DCB, 1626 "The shared pool size for the port is negative %d.\n", 1627 shared_pool_size); 1628 } 1629 } 1630 1631 /** 1632 * i40e_dcb_hw_rx_pb_config 1633 * @hw: pointer to the hw struct 1634 * @old_pb_cfg: Existing Rx Packet buffer configuration 1635 * @new_pb_cfg: New Rx Packet buffer configuration 1636 * 1637 * Program the Rx Packet Buffer registers. 1638 **/ 1639 void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw, 1640 struct i40e_rx_pb_config *old_pb_cfg, 1641 struct i40e_rx_pb_config *new_pb_cfg) 1642 { 1643 u32 old_val; 1644 u32 new_val; 1645 u32 reg; 1646 u8 i; 1647 1648 /* The Rx Packet buffer register programming needs to be done in a 1649 * certain order and the following code is based on that 1650 * requirement. 1651 */ 1652 1653 /* Program the shared pool low water mark per port if decreasing */ 1654 old_val = old_pb_cfg->shared_pool_low_wm; 1655 new_val = new_pb_cfg->shared_pool_low_wm; 1656 if (new_val < old_val) { 1657 reg = rd32(hw, I40E_PRTRPB_SLW); 1658 reg &= ~I40E_PRTRPB_SLW_SLW_MASK; 1659 reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val); 1660 wr32(hw, I40E_PRTRPB_SLW, reg); 1661 } 1662 1663 /* Program the shared pool low threshold and tc pool 1664 * low water mark per TC that are decreasing. 1665 */ 1666 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1667 old_val = old_pb_cfg->shared_pool_low_thresh[i]; 1668 new_val = new_pb_cfg->shared_pool_low_thresh[i]; 1669 if (new_val < old_val) { 1670 reg = rd32(hw, I40E_PRTRPB_SLT(i)); 1671 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK; 1672 reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK, 1673 new_val); 1674 wr32(hw, I40E_PRTRPB_SLT(i), reg); 1675 } 1676 1677 old_val = old_pb_cfg->tc_pool_low_wm[i]; 1678 new_val = new_pb_cfg->tc_pool_low_wm[i]; 1679 if (new_val < old_val) { 1680 reg = rd32(hw, I40E_PRTRPB_DLW(i)); 1681 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK; 1682 reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK, 1683 new_val); 1684 wr32(hw, I40E_PRTRPB_DLW(i), reg); 1685 } 1686 } 1687 1688 /* Program the shared pool high water mark per port if decreasing */ 1689 old_val = old_pb_cfg->shared_pool_high_wm; 1690 new_val = new_pb_cfg->shared_pool_high_wm; 1691 if (new_val < old_val) { 1692 reg = rd32(hw, I40E_PRTRPB_SHW); 1693 reg &= ~I40E_PRTRPB_SHW_SHW_MASK; 1694 reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val); 1695 wr32(hw, I40E_PRTRPB_SHW, reg); 1696 } 1697 1698 /* Program the shared pool high threshold and tc pool 1699 * high water mark per TC that are decreasing. 1700 */ 1701 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1702 old_val = old_pb_cfg->shared_pool_high_thresh[i]; 1703 new_val = new_pb_cfg->shared_pool_high_thresh[i]; 1704 if (new_val < old_val) { 1705 reg = rd32(hw, I40E_PRTRPB_SHT(i)); 1706 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK; 1707 reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK, 1708 new_val); 1709 wr32(hw, I40E_PRTRPB_SHT(i), reg); 1710 } 1711 1712 old_val = old_pb_cfg->tc_pool_high_wm[i]; 1713 new_val = new_pb_cfg->tc_pool_high_wm[i]; 1714 if (new_val < old_val) { 1715 reg = rd32(hw, I40E_PRTRPB_DHW(i)); 1716 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK; 1717 reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK, 1718 new_val); 1719 wr32(hw, I40E_PRTRPB_DHW(i), reg); 1720 } 1721 } 1722 1723 /* Write Dedicated Pool Sizes per TC */ 1724 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1725 new_val = new_pb_cfg->tc_pool_size[i]; 1726 reg = rd32(hw, I40E_PRTRPB_DPS(i)); 1727 reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK; 1728 reg |= FIELD_PREP(I40E_PRTRPB_DPS_DPS_TCN_MASK, new_val); 1729 wr32(hw, I40E_PRTRPB_DPS(i), reg); 1730 } 1731 1732 /* Write Shared Pool Size per port */ 1733 new_val = new_pb_cfg->shared_pool_size; 1734 reg = rd32(hw, I40E_PRTRPB_SPS); 1735 reg &= ~I40E_PRTRPB_SPS_SPS_MASK; 1736 reg |= FIELD_PREP(I40E_PRTRPB_SPS_SPS_MASK, new_val); 1737 wr32(hw, I40E_PRTRPB_SPS, reg); 1738 1739 /* Program the shared pool low water mark per port if increasing */ 1740 old_val = old_pb_cfg->shared_pool_low_wm; 1741 new_val = new_pb_cfg->shared_pool_low_wm; 1742 if (new_val > old_val) { 1743 reg = rd32(hw, I40E_PRTRPB_SLW); 1744 reg &= ~I40E_PRTRPB_SLW_SLW_MASK; 1745 reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val); 1746 wr32(hw, I40E_PRTRPB_SLW, reg); 1747 } 1748 1749 /* Program the shared pool low threshold and tc pool 1750 * low water mark per TC that are increasing. 1751 */ 1752 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1753 old_val = old_pb_cfg->shared_pool_low_thresh[i]; 1754 new_val = new_pb_cfg->shared_pool_low_thresh[i]; 1755 if (new_val > old_val) { 1756 reg = rd32(hw, I40E_PRTRPB_SLT(i)); 1757 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK; 1758 reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK, 1759 new_val); 1760 wr32(hw, I40E_PRTRPB_SLT(i), reg); 1761 } 1762 1763 old_val = old_pb_cfg->tc_pool_low_wm[i]; 1764 new_val = new_pb_cfg->tc_pool_low_wm[i]; 1765 if (new_val > old_val) { 1766 reg = rd32(hw, I40E_PRTRPB_DLW(i)); 1767 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK; 1768 reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK, 1769 new_val); 1770 wr32(hw, I40E_PRTRPB_DLW(i), reg); 1771 } 1772 } 1773 1774 /* Program the shared pool high water mark per port if increasing */ 1775 old_val = old_pb_cfg->shared_pool_high_wm; 1776 new_val = new_pb_cfg->shared_pool_high_wm; 1777 if (new_val > old_val) { 1778 reg = rd32(hw, I40E_PRTRPB_SHW); 1779 reg &= ~I40E_PRTRPB_SHW_SHW_MASK; 1780 reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val); 1781 wr32(hw, I40E_PRTRPB_SHW, reg); 1782 } 1783 1784 /* Program the shared pool high threshold and tc pool 1785 * high water mark per TC that are increasing. 1786 */ 1787 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 1788 old_val = old_pb_cfg->shared_pool_high_thresh[i]; 1789 new_val = new_pb_cfg->shared_pool_high_thresh[i]; 1790 if (new_val > old_val) { 1791 reg = rd32(hw, I40E_PRTRPB_SHT(i)); 1792 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK; 1793 reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK, 1794 new_val); 1795 wr32(hw, I40E_PRTRPB_SHT(i), reg); 1796 } 1797 1798 old_val = old_pb_cfg->tc_pool_high_wm[i]; 1799 new_val = new_pb_cfg->tc_pool_high_wm[i]; 1800 if (new_val > old_val) { 1801 reg = rd32(hw, I40E_PRTRPB_DHW(i)); 1802 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK; 1803 reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK, 1804 new_val); 1805 wr32(hw, I40E_PRTRPB_DHW(i), reg); 1806 } 1807 } 1808 } 1809 1810 /** 1811 * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM 1812 * @hw: pointer to the HW structure 1813 * @lldp_cfg: pointer to hold lldp configuration variables 1814 * @module: address of the module pointer 1815 * @word_offset: offset of LLDP configuration 1816 * 1817 * Reads the LLDP configuration data from NVM using passed addresses 1818 **/ 1819 static int _i40e_read_lldp_cfg(struct i40e_hw *hw, 1820 struct i40e_lldp_variables *lldp_cfg, 1821 u8 module, u32 word_offset) 1822 { 1823 u32 address, offset = (2 * word_offset); 1824 __le16 raw_mem; 1825 int ret; 1826 u16 mem; 1827 1828 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1829 if (ret) 1830 return ret; 1831 1832 ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem, 1833 true, NULL); 1834 i40e_release_nvm(hw); 1835 if (ret) 1836 return ret; 1837 1838 mem = le16_to_cpu(raw_mem); 1839 /* Check if this pointer needs to be read in word size or 4K sector 1840 * units. 1841 */ 1842 if (mem & I40E_PTR_TYPE) 1843 address = (0x7FFF & mem) * 4096; 1844 else 1845 address = (0x7FFF & mem) * 2; 1846 1847 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1848 if (ret) 1849 goto err_lldp_cfg; 1850 1851 ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem, 1852 true, NULL); 1853 i40e_release_nvm(hw); 1854 if (ret) 1855 return ret; 1856 1857 mem = le16_to_cpu(raw_mem); 1858 offset = mem + word_offset; 1859 offset *= 2; 1860 1861 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1862 if (ret) 1863 goto err_lldp_cfg; 1864 1865 ret = i40e_aq_read_nvm(hw, 0, address + offset, 1866 sizeof(struct i40e_lldp_variables), lldp_cfg, 1867 true, NULL); 1868 i40e_release_nvm(hw); 1869 1870 err_lldp_cfg: 1871 return ret; 1872 } 1873 1874 /** 1875 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM 1876 * @hw: pointer to the HW structure 1877 * @lldp_cfg: pointer to hold lldp configuration variables 1878 * 1879 * Reads the LLDP configuration data from NVM 1880 **/ 1881 int i40e_read_lldp_cfg(struct i40e_hw *hw, 1882 struct i40e_lldp_variables *lldp_cfg) 1883 { 1884 int ret = 0; 1885 u32 mem; 1886 1887 if (!lldp_cfg) 1888 return -EINVAL; 1889 1890 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 1891 if (ret) 1892 return ret; 1893 1894 ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem), 1895 &mem, true, NULL); 1896 i40e_release_nvm(hw); 1897 if (ret) 1898 return ret; 1899 1900 /* Read a bit that holds information whether we are running flat or 1901 * structured NVM image. Flat image has LLDP configuration in shadow 1902 * ram, so there is a need to pass different addresses for both cases. 1903 */ 1904 if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) { 1905 /* Flat NVM case */ 1906 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR, 1907 I40E_SR_LLDP_CFG_PTR); 1908 } else { 1909 /* Good old structured NVM image */ 1910 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR, 1911 I40E_NVM_LLDP_CFG_PTR); 1912 } 1913 1914 return ret; 1915 } 1916