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