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