1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2019, Intel Corporation. */ 3 4 #include "ice_common.h" 5 #include "ice_sched.h" 6 #include "ice_dcb.h" 7 8 /** 9 * ice_aq_get_lldp_mib 10 * @hw: pointer to the HW struct 11 * @bridge_type: type of bridge requested 12 * @mib_type: Local, Remote or both Local and Remote MIBs 13 * @buf: pointer to the caller-supplied buffer to store the MIB block 14 * @buf_size: size of the buffer (in bytes) 15 * @local_len: length of the returned Local LLDP MIB 16 * @remote_len: length of the returned Remote LLDP MIB 17 * @cd: pointer to command details structure or NULL 18 * 19 * Requests the complete LLDP MIB (entire packet). (0x0A00) 20 */ 21 static int 22 ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf, 23 u16 buf_size, u16 *local_len, u16 *remote_len, 24 struct ice_sq_cd *cd) 25 { 26 struct ice_aqc_lldp_get_mib *cmd; 27 struct ice_aq_desc desc; 28 int status; 29 30 cmd = &desc.params.lldp_get_mib; 31 32 if (buf_size == 0 || !buf) 33 return -EINVAL; 34 35 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_get_mib); 36 37 cmd->type = mib_type & ICE_AQ_LLDP_MIB_TYPE_M; 38 cmd->type |= FIELD_PREP(ICE_AQ_LLDP_BRID_TYPE_M, bridge_type); 39 40 desc.datalen = cpu_to_le16(buf_size); 41 42 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 43 if (!status) { 44 if (local_len) 45 *local_len = le16_to_cpu(cmd->local_len); 46 if (remote_len) 47 *remote_len = le16_to_cpu(cmd->remote_len); 48 } 49 50 return status; 51 } 52 53 /** 54 * ice_aq_cfg_lldp_mib_change 55 * @hw: pointer to the HW struct 56 * @ena_update: Enable or Disable event posting 57 * @cd: pointer to command details structure or NULL 58 * 59 * Enable or Disable posting of an event on ARQ when LLDP MIB 60 * associated with the interface changes (0x0A01) 61 */ 62 static int 63 ice_aq_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_update, 64 struct ice_sq_cd *cd) 65 { 66 struct ice_aqc_lldp_set_mib_change *cmd; 67 struct ice_aq_desc desc; 68 69 cmd = &desc.params.lldp_set_event; 70 71 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_mib_change); 72 73 if (!ena_update) 74 cmd->command |= ICE_AQ_LLDP_MIB_UPDATE_DIS; 75 else 76 cmd->command |= FIELD_PREP(ICE_AQ_LLDP_MIB_PENDING_M, 77 ICE_AQ_LLDP_MIB_PENDING_ENABLE); 78 79 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 80 } 81 82 /** 83 * ice_aq_stop_lldp 84 * @hw: pointer to the HW struct 85 * @shutdown_lldp_agent: True if LLDP Agent needs to be Shutdown 86 * False if LLDP Agent needs to be Stopped 87 * @persist: True if Stop/Shutdown of LLDP Agent needs to be persistent across 88 * reboots 89 * @cd: pointer to command details structure or NULL 90 * 91 * Stop or Shutdown the embedded LLDP Agent (0x0A05) 92 */ 93 int 94 ice_aq_stop_lldp(struct ice_hw *hw, bool shutdown_lldp_agent, bool persist, 95 struct ice_sq_cd *cd) 96 { 97 struct ice_aqc_lldp_stop *cmd; 98 struct ice_aq_desc desc; 99 100 cmd = &desc.params.lldp_stop; 101 102 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_stop); 103 104 if (shutdown_lldp_agent) 105 cmd->command |= ICE_AQ_LLDP_AGENT_SHUTDOWN; 106 107 if (persist) 108 cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_DIS; 109 110 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 111 } 112 113 /** 114 * ice_aq_start_lldp 115 * @hw: pointer to the HW struct 116 * @persist: True if Start of LLDP Agent needs to be persistent across reboots 117 * @cd: pointer to command details structure or NULL 118 * 119 * Start the embedded LLDP Agent on all ports. (0x0A06) 120 */ 121 int ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd) 122 { 123 struct ice_aqc_lldp_start *cmd; 124 struct ice_aq_desc desc; 125 126 cmd = &desc.params.lldp_start; 127 128 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start); 129 130 cmd->command = ICE_AQ_LLDP_AGENT_START; 131 132 if (persist) 133 cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_ENA; 134 135 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 136 } 137 138 /** 139 * ice_get_dcbx_status 140 * @hw: pointer to the HW struct 141 * 142 * Get the DCBX status from the Firmware 143 */ 144 static u8 ice_get_dcbx_status(struct ice_hw *hw) 145 { 146 u32 reg; 147 148 reg = rd32(hw, PRTDCB_GENS); 149 return FIELD_GET(PRTDCB_GENS_DCBX_STATUS_M, reg); 150 } 151 152 /** 153 * ice_parse_ieee_ets_common_tlv 154 * @buf: Data buffer to be parsed for ETS CFG/REC data 155 * @ets_cfg: Container to store parsed data 156 * 157 * Parses the common data of IEEE 802.1Qaz ETS CFG/REC TLV 158 */ 159 static void 160 ice_parse_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 161 { 162 u8 offset = 0; 163 int i; 164 165 /* Priority Assignment Table (4 octets) 166 * Octets:| 1 | 2 | 3 | 4 | 167 * ----------------------------------------- 168 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 169 * ----------------------------------------- 170 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 171 * ----------------------------------------- 172 */ 173 for (i = 0; i < 4; i++) { 174 ets_cfg->prio_table[i * 2] = 175 FIELD_GET(ICE_IEEE_ETS_PRIO_1_M, buf[offset]); 176 ets_cfg->prio_table[i * 2 + 1] = 177 FIELD_GET(ICE_IEEE_ETS_PRIO_0_M, buf[offset]); 178 offset++; 179 } 180 181 /* TC Bandwidth Table (8 octets) 182 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 183 * --------------------------------- 184 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 185 * --------------------------------- 186 * 187 * TSA Assignment Table (8 octets) 188 * Octets:| 9 | 10| 11| 12| 13| 14| 15| 16| 189 * --------------------------------- 190 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 191 * --------------------------------- 192 */ 193 ice_for_each_traffic_class(i) { 194 ets_cfg->tcbwtable[i] = buf[offset]; 195 ets_cfg->tsatable[i] = buf[ICE_MAX_TRAFFIC_CLASS + offset++]; 196 } 197 } 198 199 /** 200 * ice_parse_ieee_etscfg_tlv 201 * @tlv: IEEE 802.1Qaz ETS CFG TLV 202 * @dcbcfg: Local store to update ETS CFG data 203 * 204 * Parses IEEE 802.1Qaz ETS CFG TLV 205 */ 206 static void 207 ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv *tlv, 208 struct ice_dcbx_cfg *dcbcfg) 209 { 210 struct ice_dcb_ets_cfg *etscfg; 211 u8 *buf = tlv->tlvinfo; 212 213 /* First Octet post subtype 214 * -------------------------- 215 * |will-|CBS | Re- | Max | 216 * |ing | |served| TCs | 217 * -------------------------- 218 * |1bit | 1bit|3 bits|3bits| 219 */ 220 etscfg = &dcbcfg->etscfg; 221 etscfg->willing = FIELD_GET(ICE_IEEE_ETS_WILLING_M, buf[0]); 222 etscfg->cbs = FIELD_GET(ICE_IEEE_ETS_CBS_M, buf[0]); 223 etscfg->maxtcs = FIELD_GET(ICE_IEEE_ETS_MAXTC_M, buf[0]); 224 225 /* Begin parsing at Priority Assignment Table (offset 1 in buf) */ 226 ice_parse_ieee_ets_common_tlv(&buf[1], etscfg); 227 } 228 229 /** 230 * ice_parse_ieee_etsrec_tlv 231 * @tlv: IEEE 802.1Qaz ETS REC TLV 232 * @dcbcfg: Local store to update ETS REC data 233 * 234 * Parses IEEE 802.1Qaz ETS REC TLV 235 */ 236 static void 237 ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 238 struct ice_dcbx_cfg *dcbcfg) 239 { 240 u8 *buf = tlv->tlvinfo; 241 242 /* Begin parsing at Priority Assignment Table (offset 1 in buf) */ 243 ice_parse_ieee_ets_common_tlv(&buf[1], &dcbcfg->etsrec); 244 } 245 246 /** 247 * ice_parse_ieee_pfccfg_tlv 248 * @tlv: IEEE 802.1Qaz PFC CFG TLV 249 * @dcbcfg: Local store to update PFC CFG data 250 * 251 * Parses IEEE 802.1Qaz PFC CFG TLV 252 */ 253 static void 254 ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv *tlv, 255 struct ice_dcbx_cfg *dcbcfg) 256 { 257 u8 *buf = tlv->tlvinfo; 258 259 /* ---------------------------------------- 260 * |will-|MBC | Re- | PFC | PFC Enable | 261 * |ing | |served| cap | | 262 * ----------------------------------------- 263 * |1bit | 1bit|2 bits|4bits| 1 octet | 264 */ 265 dcbcfg->pfc.willing = FIELD_GET(ICE_IEEE_PFC_WILLING_M, buf[0]); 266 dcbcfg->pfc.mbc = FIELD_GET(ICE_IEEE_PFC_MBC_M, buf[0]); 267 dcbcfg->pfc.pfccap = FIELD_GET(ICE_IEEE_PFC_CAP_M, buf[0]); 268 dcbcfg->pfc.pfcena = buf[1]; 269 } 270 271 /** 272 * ice_parse_ieee_app_tlv 273 * @tlv: IEEE 802.1Qaz APP TLV 274 * @dcbcfg: Local store to update APP PRIO data 275 * 276 * Parses IEEE 802.1Qaz APP PRIO TLV 277 */ 278 static void 279 ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv *tlv, 280 struct ice_dcbx_cfg *dcbcfg) 281 { 282 u16 offset = 0; 283 u16 typelen; 284 int i = 0; 285 u16 len; 286 u8 *buf; 287 288 typelen = ntohs(tlv->typelen); 289 len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 290 buf = tlv->tlvinfo; 291 292 /* Removing sizeof(ouisubtype) and reserved byte from len. 293 * Remaining len div 3 is number of APP TLVs. 294 */ 295 len -= (sizeof(tlv->ouisubtype) + 1); 296 297 /* Move offset to App Priority Table */ 298 offset++; 299 300 /* Application Priority Table (3 octets) 301 * Octets:| 1 | 2 | 3 | 302 * ----------------------------------------- 303 * |Priority|Rsrvd| Sel | Protocol ID | 304 * ----------------------------------------- 305 * Bits:|23 21|20 19|18 16|15 0| 306 * ----------------------------------------- 307 */ 308 while (offset < len) { 309 dcbcfg->app[i].priority = FIELD_GET(ICE_IEEE_APP_PRIO_M, 310 buf[offset]); 311 dcbcfg->app[i].selector = FIELD_GET(ICE_IEEE_APP_SEL_M, 312 buf[offset]); 313 dcbcfg->app[i].prot_id = (buf[offset + 1] << 0x8) | 314 buf[offset + 2]; 315 /* Move to next app */ 316 offset += 3; 317 i++; 318 if (i >= ICE_DCBX_MAX_APPS) 319 break; 320 } 321 322 dcbcfg->numapps = i; 323 } 324 325 /** 326 * ice_parse_ieee_tlv 327 * @tlv: IEEE 802.1Qaz TLV 328 * @dcbcfg: Local store to update ETS REC data 329 * 330 * Get the TLV subtype and send it to parsing function 331 * based on the subtype value 332 */ 333 static void 334 ice_parse_ieee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 335 { 336 u32 ouisubtype; 337 u8 subtype; 338 339 ouisubtype = ntohl(tlv->ouisubtype); 340 subtype = FIELD_GET(ICE_LLDP_TLV_SUBTYPE_M, ouisubtype); 341 switch (subtype) { 342 case ICE_IEEE_SUBTYPE_ETS_CFG: 343 ice_parse_ieee_etscfg_tlv(tlv, dcbcfg); 344 break; 345 case ICE_IEEE_SUBTYPE_ETS_REC: 346 ice_parse_ieee_etsrec_tlv(tlv, dcbcfg); 347 break; 348 case ICE_IEEE_SUBTYPE_PFC_CFG: 349 ice_parse_ieee_pfccfg_tlv(tlv, dcbcfg); 350 break; 351 case ICE_IEEE_SUBTYPE_APP_PRI: 352 ice_parse_ieee_app_tlv(tlv, dcbcfg); 353 break; 354 default: 355 break; 356 } 357 } 358 359 /** 360 * ice_parse_cee_pgcfg_tlv 361 * @tlv: CEE DCBX PG CFG TLV 362 * @dcbcfg: Local store to update ETS CFG data 363 * 364 * Parses CEE DCBX PG CFG TLV 365 */ 366 static void 367 ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv *tlv, 368 struct ice_dcbx_cfg *dcbcfg) 369 { 370 struct ice_dcb_ets_cfg *etscfg; 371 u8 *buf = tlv->tlvinfo; 372 u16 offset = 0; 373 int i; 374 375 etscfg = &dcbcfg->etscfg; 376 377 if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M) 378 etscfg->willing = 1; 379 380 etscfg->cbs = 0; 381 /* Priority Group Table (4 octets) 382 * Octets:| 1 | 2 | 3 | 4 | 383 * ----------------------------------------- 384 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 385 * ----------------------------------------- 386 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 387 * ----------------------------------------- 388 */ 389 for (i = 0; i < 4; i++) { 390 etscfg->prio_table[i * 2] = 391 FIELD_GET(ICE_CEE_PGID_PRIO_1_M, buf[offset]); 392 etscfg->prio_table[i * 2 + 1] = 393 FIELD_GET(ICE_CEE_PGID_PRIO_0_M, buf[offset]); 394 offset++; 395 } 396 397 /* PG Percentage Table (8 octets) 398 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 399 * --------------------------------- 400 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7| 401 * --------------------------------- 402 */ 403 ice_for_each_traffic_class(i) { 404 etscfg->tcbwtable[i] = buf[offset++]; 405 406 if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT) 407 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 408 else 409 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 410 } 411 412 /* Number of TCs supported (1 octet) */ 413 etscfg->maxtcs = buf[offset]; 414 } 415 416 /** 417 * ice_parse_cee_pfccfg_tlv 418 * @tlv: CEE DCBX PFC CFG TLV 419 * @dcbcfg: Local store to update PFC CFG data 420 * 421 * Parses CEE DCBX PFC CFG TLV 422 */ 423 static void 424 ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv, 425 struct ice_dcbx_cfg *dcbcfg) 426 { 427 u8 *buf = tlv->tlvinfo; 428 429 if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M) 430 dcbcfg->pfc.willing = 1; 431 432 /* ------------------------ 433 * | PFC Enable | PFC TCs | 434 * ------------------------ 435 * | 1 octet | 1 octet | 436 */ 437 dcbcfg->pfc.pfcena = buf[0]; 438 dcbcfg->pfc.pfccap = buf[1]; 439 } 440 441 /** 442 * ice_parse_cee_app_tlv 443 * @tlv: CEE DCBX APP TLV 444 * @dcbcfg: Local store to update APP PRIO data 445 * 446 * Parses CEE DCBX APP PRIO TLV 447 */ 448 static void 449 ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 450 { 451 u16 len, typelen, offset = 0; 452 struct ice_cee_app_prio *app; 453 u8 i; 454 455 typelen = ntohs(tlv->hdr.typelen); 456 len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 457 458 dcbcfg->numapps = len / sizeof(*app); 459 if (!dcbcfg->numapps) 460 return; 461 if (dcbcfg->numapps > ICE_DCBX_MAX_APPS) 462 dcbcfg->numapps = ICE_DCBX_MAX_APPS; 463 464 for (i = 0; i < dcbcfg->numapps; i++) { 465 u8 up, selector; 466 467 app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset); 468 for (up = 0; up < ICE_MAX_USER_PRIORITY; up++) 469 if (app->prio_map & BIT(up)) 470 break; 471 472 dcbcfg->app[i].priority = up; 473 474 /* Get Selector from lower 2 bits, and convert to IEEE */ 475 selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M); 476 switch (selector) { 477 case ICE_CEE_APP_SEL_ETHTYPE: 478 dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE; 479 break; 480 case ICE_CEE_APP_SEL_TCPIP: 481 dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP; 482 break; 483 default: 484 /* Keep selector as it is for unknown types */ 485 dcbcfg->app[i].selector = selector; 486 } 487 488 dcbcfg->app[i].prot_id = ntohs(app->protocol); 489 /* Move to next app */ 490 offset += sizeof(*app); 491 } 492 } 493 494 /** 495 * ice_parse_cee_tlv 496 * @tlv: CEE DCBX TLV 497 * @dcbcfg: Local store to update DCBX config data 498 * 499 * Get the TLV subtype and send it to parsing function 500 * based on the subtype value 501 */ 502 static void 503 ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 504 { 505 struct ice_cee_feat_tlv *sub_tlv; 506 u8 subtype, feat_tlv_count = 0; 507 u16 len, tlvlen, typelen; 508 u32 ouisubtype; 509 510 ouisubtype = ntohl(tlv->ouisubtype); 511 subtype = FIELD_GET(ICE_LLDP_TLV_SUBTYPE_M, ouisubtype); 512 /* Return if not CEE DCBX */ 513 if (subtype != ICE_CEE_DCBX_TYPE) 514 return; 515 516 typelen = ntohs(tlv->typelen); 517 tlvlen = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 518 len = sizeof(tlv->typelen) + sizeof(ouisubtype) + 519 sizeof(struct ice_cee_ctrl_tlv); 520 /* Return if no CEE DCBX Feature TLVs */ 521 if (tlvlen <= len) 522 return; 523 524 sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len); 525 while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) { 526 u16 sublen; 527 528 typelen = ntohs(sub_tlv->hdr.typelen); 529 sublen = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 530 subtype = FIELD_GET(ICE_LLDP_TLV_TYPE_M, typelen); 531 switch (subtype) { 532 case ICE_CEE_SUBTYPE_PG_CFG: 533 ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); 534 break; 535 case ICE_CEE_SUBTYPE_PFC_CFG: 536 ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); 537 break; 538 case ICE_CEE_SUBTYPE_APP_PRI: 539 ice_parse_cee_app_tlv(sub_tlv, dcbcfg); 540 break; 541 default: 542 return; /* Invalid Sub-type return */ 543 } 544 feat_tlv_count++; 545 /* Move to next sub TLV */ 546 sub_tlv = (struct ice_cee_feat_tlv *) 547 ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) + 548 sublen); 549 } 550 } 551 552 /** 553 * ice_parse_org_tlv 554 * @tlv: Organization specific TLV 555 * @dcbcfg: Local store to update ETS REC data 556 * 557 * Currently IEEE 802.1Qaz and CEE DCBX TLV are supported, others 558 * will be returned 559 */ 560 static void 561 ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 562 { 563 u32 ouisubtype; 564 u32 oui; 565 566 ouisubtype = ntohl(tlv->ouisubtype); 567 oui = FIELD_GET(ICE_LLDP_TLV_OUI_M, ouisubtype); 568 switch (oui) { 569 case ICE_IEEE_8021QAZ_OUI: 570 ice_parse_ieee_tlv(tlv, dcbcfg); 571 break; 572 case ICE_CEE_DCBX_OUI: 573 ice_parse_cee_tlv(tlv, dcbcfg); 574 break; 575 default: 576 break; /* Other OUIs not supported */ 577 } 578 } 579 580 /** 581 * ice_lldp_to_dcb_cfg 582 * @lldpmib: LLDPDU to be parsed 583 * @dcbcfg: store for LLDPDU data 584 * 585 * Parse DCB configuration from the LLDPDU 586 */ 587 static int ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg) 588 { 589 struct ice_lldp_org_tlv *tlv; 590 u16 offset = 0; 591 int ret = 0; 592 u16 typelen; 593 u16 type; 594 u16 len; 595 596 if (!lldpmib || !dcbcfg) 597 return -EINVAL; 598 599 /* set to the start of LLDPDU */ 600 lldpmib += ETH_HLEN; 601 tlv = (struct ice_lldp_org_tlv *)lldpmib; 602 while (1) { 603 typelen = ntohs(tlv->typelen); 604 type = FIELD_GET(ICE_LLDP_TLV_TYPE_M, typelen); 605 len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 606 offset += sizeof(typelen) + len; 607 608 /* END TLV or beyond LLDPDU size */ 609 if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE) 610 break; 611 612 switch (type) { 613 case ICE_TLV_TYPE_ORG: 614 ice_parse_org_tlv(tlv, dcbcfg); 615 break; 616 default: 617 break; 618 } 619 620 /* Move to next TLV */ 621 tlv = (struct ice_lldp_org_tlv *) 622 ((char *)tlv + sizeof(tlv->typelen) + len); 623 } 624 625 return ret; 626 } 627 628 /** 629 * ice_aq_get_dcb_cfg 630 * @hw: pointer to the HW struct 631 * @mib_type: MIB type for the query 632 * @bridgetype: bridge type for the query (remote) 633 * @dcbcfg: store for LLDPDU data 634 * 635 * Query DCB configuration from the firmware 636 */ 637 int 638 ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype, 639 struct ice_dcbx_cfg *dcbcfg) 640 { 641 u8 *lldpmib; 642 int ret; 643 644 /* Allocate the LLDPDU */ 645 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL); 646 if (!lldpmib) 647 return -ENOMEM; 648 649 ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib, 650 ICE_LLDPDU_SIZE, NULL, NULL, NULL); 651 652 if (!ret) 653 /* Parse LLDP MIB to get DCB configuration */ 654 ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg); 655 656 devm_kfree(ice_hw_to_dev(hw), lldpmib); 657 658 return ret; 659 } 660 661 /** 662 * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW 663 * @hw: pointer to the HW struct 664 * @start_dcbx_agent: True if DCBX Agent needs to be started 665 * False if DCBX Agent needs to be stopped 666 * @dcbx_agent_status: FW indicates back the DCBX agent status 667 * True if DCBX Agent is active 668 * False if DCBX Agent is stopped 669 * @cd: pointer to command details structure or NULL 670 * 671 * Start/Stop the embedded dcbx Agent. In case that this wrapper function 672 * returns 0, caller will need to check if FW returns back the same 673 * value as stated in dcbx_agent_status, and react accordingly. (0x0A09) 674 */ 675 int 676 ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent, 677 bool *dcbx_agent_status, struct ice_sq_cd *cd) 678 { 679 struct ice_aqc_lldp_stop_start_specific_agent *cmd; 680 struct ice_aq_desc desc; 681 u16 opcode; 682 int status; 683 684 cmd = &desc.params.lldp_agent_ctrl; 685 686 opcode = ice_aqc_opc_lldp_stop_start_specific_agent; 687 688 ice_fill_dflt_direct_cmd_desc(&desc, opcode); 689 690 if (start_dcbx_agent) 691 cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX; 692 693 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 694 695 *dcbx_agent_status = false; 696 697 if (!status && 698 cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX) 699 *dcbx_agent_status = true; 700 701 return status; 702 } 703 704 /** 705 * ice_aq_get_cee_dcb_cfg 706 * @hw: pointer to the HW struct 707 * @buff: response buffer that stores CEE operational configuration 708 * @cd: pointer to command details structure or NULL 709 * 710 * Get CEE DCBX mode operational configuration from firmware (0x0A07) 711 */ 712 static int 713 ice_aq_get_cee_dcb_cfg(struct ice_hw *hw, 714 struct ice_aqc_get_cee_dcb_cfg_resp *buff, 715 struct ice_sq_cd *cd) 716 { 717 struct ice_aq_desc desc; 718 719 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg); 720 721 return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd); 722 } 723 724 /** 725 * ice_aq_set_pfc_mode - Set PFC mode 726 * @hw: pointer to the HW struct 727 * @pfc_mode: value of PFC mode to set 728 * @cd: pointer to command details structure or NULL 729 * 730 * This AQ call configures the PFC mode to DSCP-based PFC mode or 731 * VLAN-based PFC (0x0303) 732 */ 733 int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd) 734 { 735 struct ice_aqc_set_query_pfc_mode *cmd; 736 struct ice_aq_desc desc; 737 int status; 738 739 if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC) 740 return -EINVAL; 741 742 cmd = &desc.params.set_query_pfc_mode; 743 744 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode); 745 746 cmd->pfc_mode = pfc_mode; 747 748 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 749 if (status) 750 return status; 751 752 /* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is 753 * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has 754 * been executed, check if cmd->pfc_mode is what was requested. If not, 755 * return an error. 756 */ 757 if (cmd->pfc_mode != pfc_mode) 758 return -EOPNOTSUPP; 759 760 return 0; 761 } 762 763 /** 764 * ice_cee_to_dcb_cfg 765 * @cee_cfg: pointer to CEE configuration struct 766 * @pi: port information structure 767 * 768 * Convert CEE configuration from firmware to DCB configuration 769 */ 770 static void 771 ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, 772 struct ice_port_info *pi) 773 { 774 u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); 775 u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift, j; 776 u8 i, err, sync, oper, app_index, ice_app_sel_type; 777 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); 778 u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; 779 struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg; 780 u16 ice_app_prot_id_type; 781 782 dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 783 dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE; 784 dcbcfg->tlv_status = tlv_status; 785 786 /* CEE PG data */ 787 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 788 789 /* Note that the FW creates the oper_prio_tc nibbles reversed 790 * from those in the CEE Priority Group sub-TLV. 791 */ 792 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 793 dcbcfg->etscfg.prio_table[i * 2] = 794 FIELD_GET(ICE_CEE_PGID_PRIO_0_M, 795 cee_cfg->oper_prio_tc[i]); 796 dcbcfg->etscfg.prio_table[i * 2 + 1] = 797 FIELD_GET(ICE_CEE_PGID_PRIO_1_M, 798 cee_cfg->oper_prio_tc[i]); 799 } 800 801 ice_for_each_traffic_class(i) { 802 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 803 804 if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) { 805 /* Map it to next empty TC */ 806 dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1; 807 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 808 } else { 809 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 810 } 811 } 812 813 /* CEE PFC data */ 814 dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en; 815 dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS; 816 817 /* CEE APP TLV data */ 818 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 819 cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg; 820 else 821 cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg; 822 823 app_index = 0; 824 for (i = 0; i < 3; i++) { 825 if (i == 0) { 826 /* FCoE APP */ 827 ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M; 828 ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S; 829 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M; 830 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S; 831 ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 832 ice_app_prot_id_type = ETH_P_FCOE; 833 } else if (i == 1) { 834 /* iSCSI APP */ 835 ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M; 836 ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S; 837 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M; 838 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S; 839 ice_app_sel_type = ICE_APP_SEL_TCPIP; 840 ice_app_prot_id_type = ISCSI_LISTEN_PORT; 841 842 for (j = 0; j < cmp_dcbcfg->numapps; j++) { 843 u16 prot_id = cmp_dcbcfg->app[j].prot_id; 844 u8 sel = cmp_dcbcfg->app[j].selector; 845 846 if (sel == ICE_APP_SEL_TCPIP && 847 (prot_id == ISCSI_LISTEN_PORT || 848 prot_id == ICE_APP_PROT_ID_ISCSI_860)) { 849 ice_app_prot_id_type = prot_id; 850 break; 851 } 852 } 853 } else { 854 /* FIP APP */ 855 ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M; 856 ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S; 857 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M; 858 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S; 859 ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 860 ice_app_prot_id_type = ETH_P_FIP; 861 } 862 863 status = (tlv_status & ice_aqc_cee_status_mask) >> 864 ice_aqc_cee_status_shift; 865 err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0; 866 sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0; 867 oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0; 868 /* Add FCoE/iSCSI/FIP APP if Error is False and 869 * Oper/Sync is True 870 */ 871 if (!err && sync && oper) { 872 dcbcfg->app[app_index].priority = 873 (app_prio & ice_aqc_cee_app_mask) >> 874 ice_aqc_cee_app_shift; 875 dcbcfg->app[app_index].selector = ice_app_sel_type; 876 dcbcfg->app[app_index].prot_id = ice_app_prot_id_type; 877 app_index++; 878 } 879 } 880 881 dcbcfg->numapps = app_index; 882 } 883 884 /** 885 * ice_get_ieee_or_cee_dcb_cfg 886 * @pi: port information structure 887 * @dcbx_mode: mode of DCBX (IEEE or CEE) 888 * 889 * Get IEEE or CEE mode DCB configuration from the Firmware 890 */ 891 static int ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode) 892 { 893 struct ice_dcbx_cfg *dcbx_cfg = NULL; 894 int ret; 895 896 if (!pi) 897 return -EINVAL; 898 899 if (dcbx_mode == ICE_DCBX_MODE_IEEE) 900 dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 901 else if (dcbx_mode == ICE_DCBX_MODE_CEE) 902 dcbx_cfg = &pi->qos_cfg.desired_dcbx_cfg; 903 904 /* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE 905 * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE 906 */ 907 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL, 908 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 909 if (ret) 910 goto out; 911 912 /* Get Remote DCB Config */ 913 dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg; 914 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE, 915 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 916 /* Don't treat ENOENT as an error for Remote MIBs */ 917 if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 918 ret = 0; 919 920 out: 921 return ret; 922 } 923 924 /** 925 * ice_get_dcb_cfg 926 * @pi: port information structure 927 * 928 * Get DCB configuration from the Firmware 929 */ 930 int ice_get_dcb_cfg(struct ice_port_info *pi) 931 { 932 struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg; 933 struct ice_dcbx_cfg *dcbx_cfg; 934 int ret; 935 936 if (!pi) 937 return -EINVAL; 938 939 ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL); 940 if (!ret) { 941 /* CEE mode */ 942 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE); 943 ice_cee_to_dcb_cfg(&cee_cfg, pi); 944 } else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) { 945 /* CEE mode not enabled try querying IEEE data */ 946 dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 947 dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE; 948 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE); 949 } 950 951 return ret; 952 } 953 954 /** 955 * ice_get_dcb_cfg_from_mib_change 956 * @pi: port information structure 957 * @event: pointer to the admin queue receive event 958 * 959 * Set DCB configuration from received MIB Change event 960 */ 961 void ice_get_dcb_cfg_from_mib_change(struct ice_port_info *pi, 962 struct ice_rq_event_info *event) 963 { 964 struct ice_dcbx_cfg *dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 965 struct ice_aqc_lldp_get_mib *mib; 966 u8 change_type, dcbx_mode; 967 968 mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw; 969 970 change_type = FIELD_GET(ICE_AQ_LLDP_MIB_TYPE_M, mib->type); 971 if (change_type == ICE_AQ_LLDP_MIB_REMOTE) 972 dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg; 973 974 dcbx_mode = FIELD_GET(ICE_AQ_LLDP_DCBX_M, mib->type); 975 976 switch (dcbx_mode) { 977 case ICE_AQ_LLDP_DCBX_IEEE: 978 dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE; 979 ice_lldp_to_dcb_cfg(event->msg_buf, dcbx_cfg); 980 break; 981 982 case ICE_AQ_LLDP_DCBX_CEE: 983 pi->qos_cfg.desired_dcbx_cfg = pi->qos_cfg.local_dcbx_cfg; 984 ice_cee_to_dcb_cfg((struct ice_aqc_get_cee_dcb_cfg_resp *) 985 event->msg_buf, pi); 986 break; 987 } 988 } 989 990 /** 991 * ice_init_dcb 992 * @hw: pointer to the HW struct 993 * @enable_mib_change: enable MIB change event 994 * 995 * Update DCB configuration from the Firmware 996 */ 997 int ice_init_dcb(struct ice_hw *hw, bool enable_mib_change) 998 { 999 struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg; 1000 int ret = 0; 1001 1002 if (!hw->func_caps.common_cap.dcb) 1003 return -EOPNOTSUPP; 1004 1005 qos_cfg->is_sw_lldp = true; 1006 1007 /* Get DCBX status */ 1008 qos_cfg->dcbx_status = ice_get_dcbx_status(hw); 1009 1010 if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DONE || 1011 qos_cfg->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS || 1012 qos_cfg->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { 1013 /* Get current DCBX configuration */ 1014 ret = ice_get_dcb_cfg(hw->port_info); 1015 if (ret) 1016 return ret; 1017 qos_cfg->is_sw_lldp = false; 1018 } else if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) { 1019 return -EBUSY; 1020 } 1021 1022 /* Configure the LLDP MIB change event */ 1023 if (enable_mib_change) { 1024 ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL); 1025 if (ret) 1026 qos_cfg->is_sw_lldp = true; 1027 } 1028 1029 return ret; 1030 } 1031 1032 /** 1033 * ice_cfg_lldp_mib_change 1034 * @hw: pointer to the HW struct 1035 * @ena_mib: enable/disable MIB change event 1036 * 1037 * Configure (disable/enable) MIB 1038 */ 1039 int ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib) 1040 { 1041 struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg; 1042 int ret; 1043 1044 if (!hw->func_caps.common_cap.dcb) 1045 return -EOPNOTSUPP; 1046 1047 /* Get DCBX status */ 1048 qos_cfg->dcbx_status = ice_get_dcbx_status(hw); 1049 1050 if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) 1051 return -EBUSY; 1052 1053 ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL); 1054 if (!ret) 1055 qos_cfg->is_sw_lldp = !ena_mib; 1056 1057 return ret; 1058 } 1059 1060 /** 1061 * ice_add_ieee_ets_common_tlv 1062 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data 1063 * @ets_cfg: Container for ice_dcb_ets_cfg data 1064 * 1065 * Populate the TLV buffer with ice_dcb_ets_cfg data 1066 */ 1067 static void 1068 ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 1069 { 1070 u8 priority0, priority1; 1071 u8 offset = 0; 1072 int i; 1073 1074 /* Priority Assignment Table (4 octets) 1075 * Octets:| 1 | 2 | 3 | 4 | 1076 * ----------------------------------------- 1077 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1078 * ----------------------------------------- 1079 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1080 * ----------------------------------------- 1081 */ 1082 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 1083 priority0 = ets_cfg->prio_table[i * 2] & 0xF; 1084 priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF; 1085 buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1; 1086 offset++; 1087 } 1088 1089 /* TC Bandwidth Table (8 octets) 1090 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1091 * --------------------------------- 1092 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1093 * --------------------------------- 1094 * 1095 * TSA Assignment 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 ice_for_each_traffic_class(i) { 1102 buf[offset] = ets_cfg->tcbwtable[i]; 1103 buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i]; 1104 offset++; 1105 } 1106 } 1107 1108 /** 1109 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 1110 * @tlv: Fill the ETS config data in IEEE format 1111 * @dcbcfg: Local store which holds the DCB Config 1112 * 1113 * Prepare IEEE 802.1Qaz ETS CFG TLV 1114 */ 1115 static void 1116 ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1117 { 1118 struct ice_dcb_ets_cfg *etscfg; 1119 u8 *buf = tlv->tlvinfo; 1120 u8 maxtcwilling = 0; 1121 u32 ouisubtype; 1122 u16 typelen; 1123 1124 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1125 ICE_IEEE_ETS_TLV_LEN); 1126 tlv->typelen = htons(typelen); 1127 1128 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1129 ICE_IEEE_SUBTYPE_ETS_CFG); 1130 tlv->ouisubtype = htonl(ouisubtype); 1131 1132 /* First Octet post subtype 1133 * -------------------------- 1134 * |will-|CBS | Re- | Max | 1135 * |ing | |served| TCs | 1136 * -------------------------- 1137 * |1bit | 1bit|3 bits|3bits| 1138 */ 1139 etscfg = &dcbcfg->etscfg; 1140 if (etscfg->willing) 1141 maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S); 1142 maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 1143 buf[0] = maxtcwilling; 1144 1145 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1146 ice_add_ieee_ets_common_tlv(&buf[1], etscfg); 1147 } 1148 1149 /** 1150 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 1151 * @tlv: Fill ETS Recommended TLV in IEEE format 1152 * @dcbcfg: Local store which holds the DCB Config 1153 * 1154 * Prepare IEEE 802.1Qaz ETS REC TLV 1155 */ 1156 static void 1157 ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 1158 struct ice_dcbx_cfg *dcbcfg) 1159 { 1160 struct ice_dcb_ets_cfg *etsrec; 1161 u8 *buf = tlv->tlvinfo; 1162 u32 ouisubtype; 1163 u16 typelen; 1164 1165 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1166 ICE_IEEE_ETS_TLV_LEN); 1167 tlv->typelen = htons(typelen); 1168 1169 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1170 ICE_IEEE_SUBTYPE_ETS_REC); 1171 tlv->ouisubtype = htonl(ouisubtype); 1172 1173 etsrec = &dcbcfg->etsrec; 1174 1175 /* First Octet is reserved */ 1176 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1177 ice_add_ieee_ets_common_tlv(&buf[1], etsrec); 1178 } 1179 1180 /** 1181 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 1182 * @tlv: Fill PFC TLV in IEEE format 1183 * @dcbcfg: Local store which holds the PFC CFG data 1184 * 1185 * Prepare IEEE 802.1Qaz PFC CFG TLV 1186 */ 1187 static void 1188 ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1189 { 1190 u8 *buf = tlv->tlvinfo; 1191 u32 ouisubtype; 1192 u16 typelen; 1193 1194 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1195 ICE_IEEE_PFC_TLV_LEN); 1196 tlv->typelen = htons(typelen); 1197 1198 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1199 ICE_IEEE_SUBTYPE_PFC_CFG); 1200 tlv->ouisubtype = htonl(ouisubtype); 1201 1202 /* ---------------------------------------- 1203 * |will-|MBC | Re- | PFC | PFC Enable | 1204 * |ing | |served| cap | | 1205 * ----------------------------------------- 1206 * |1bit | 1bit|2 bits|4bits| 1 octet | 1207 */ 1208 if (dcbcfg->pfc.willing) 1209 buf[0] = BIT(ICE_IEEE_PFC_WILLING_S); 1210 1211 if (dcbcfg->pfc.mbc) 1212 buf[0] |= BIT(ICE_IEEE_PFC_MBC_S); 1213 1214 buf[0] |= dcbcfg->pfc.pfccap & 0xF; 1215 buf[1] = dcbcfg->pfc.pfcena; 1216 } 1217 1218 /** 1219 * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 1220 * @tlv: Fill APP TLV in IEEE format 1221 * @dcbcfg: Local store which holds the APP CFG data 1222 * 1223 * Prepare IEEE 802.1Qaz APP CFG TLV 1224 */ 1225 static void 1226 ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv, 1227 struct ice_dcbx_cfg *dcbcfg) 1228 { 1229 u16 typelen, len, offset = 0; 1230 u8 priority, selector, i = 0; 1231 u8 *buf = tlv->tlvinfo; 1232 u32 ouisubtype; 1233 1234 /* No APP TLVs then just return */ 1235 if (dcbcfg->numapps == 0) 1236 return; 1237 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1238 ICE_IEEE_SUBTYPE_APP_PRI); 1239 tlv->ouisubtype = htonl(ouisubtype); 1240 1241 /* Move offset to App Priority Table */ 1242 offset++; 1243 /* Application Priority Table (3 octets) 1244 * Octets:| 1 | 2 | 3 | 1245 * ----------------------------------------- 1246 * |Priority|Rsrvd| Sel | Protocol ID | 1247 * ----------------------------------------- 1248 * Bits:|23 21|20 19|18 16|15 0| 1249 * ----------------------------------------- 1250 */ 1251 while (i < dcbcfg->numapps) { 1252 priority = dcbcfg->app[i].priority & 0x7; 1253 selector = dcbcfg->app[i].selector & 0x7; 1254 buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector; 1255 buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF; 1256 buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF; 1257 /* Move to next app */ 1258 offset += 3; 1259 i++; 1260 if (i >= ICE_DCBX_MAX_APPS) 1261 break; 1262 } 1263 /* len includes size of ouisubtype + 1 reserved + 3*numapps */ 1264 len = sizeof(tlv->ouisubtype) + 1 + (i * 3); 1265 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF)); 1266 tlv->typelen = htons(typelen); 1267 } 1268 1269 /** 1270 * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV 1271 * @tlv: location to build the TLV data 1272 * @dcbcfg: location of data to convert to TLV 1273 */ 1274 static void 1275 ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1276 { 1277 u8 *buf = tlv->tlvinfo; 1278 u32 ouisubtype; 1279 u16 typelen; 1280 int i; 1281 1282 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1283 ICE_DSCP_UP_TLV_LEN); 1284 tlv->typelen = htons(typelen); 1285 1286 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 1287 ICE_DSCP_SUBTYPE_DSCP2UP); 1288 tlv->ouisubtype = htonl(ouisubtype); 1289 1290 /* bytes 0 - 63 - IPv4 DSCP2UP LUT */ 1291 for (i = 0; i < ICE_DSCP_NUM_VAL; i++) { 1292 /* IPv4 mapping */ 1293 buf[i] = dcbcfg->dscp_map[i]; 1294 /* IPv6 mapping */ 1295 buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i]; 1296 } 1297 1298 /* byte 64 - IPv4 untagged traffic */ 1299 buf[i] = 0; 1300 1301 /* byte 144 - IPv6 untagged traffic */ 1302 buf[i + ICE_DSCP_IPV6_OFFSET] = 0; 1303 } 1304 1305 #define ICE_BYTES_PER_TC 8 1306 /** 1307 * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV 1308 * @tlv: location to build the TLV data 1309 */ 1310 static void 1311 ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv) 1312 { 1313 u8 *buf = tlv->tlvinfo; 1314 u32 ouisubtype; 1315 u16 typelen; 1316 1317 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1318 ICE_DSCP_ENF_TLV_LEN); 1319 tlv->typelen = htons(typelen); 1320 1321 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 1322 ICE_DSCP_SUBTYPE_ENFORCE); 1323 tlv->ouisubtype = htonl(ouisubtype); 1324 1325 /* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */ 1326 memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC)); 1327 } 1328 1329 /** 1330 * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV 1331 * @tlv: location to build the TLV data 1332 * @dcbcfg: location of the data to convert to TLV 1333 */ 1334 static void 1335 ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv, 1336 struct ice_dcbx_cfg *dcbcfg) 1337 { 1338 struct ice_dcb_ets_cfg *etscfg; 1339 u8 *buf = tlv->tlvinfo; 1340 u32 ouisubtype; 1341 u8 offset = 0; 1342 u16 typelen; 1343 int i; 1344 1345 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1346 ICE_DSCP_TC_BW_TLV_LEN); 1347 tlv->typelen = htons(typelen); 1348 1349 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 1350 ICE_DSCP_SUBTYPE_TCBW); 1351 tlv->ouisubtype = htonl(ouisubtype); 1352 1353 /* First Octect after subtype 1354 * ---------------------------- 1355 * | RSV | CBS | RSV | Max TCs | 1356 * | 1b | 1b | 3b | 3b | 1357 * ---------------------------- 1358 */ 1359 etscfg = &dcbcfg->etscfg; 1360 buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 1361 1362 /* bytes 1 - 4 reserved */ 1363 offset = 5; 1364 1365 /* TC BW table 1366 * bytes 0 - 7 for TC 0 - 7 1367 * 1368 * TSA Assignment table 1369 * bytes 8 - 15 for TC 0 - 7 1370 */ 1371 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { 1372 buf[offset] = etscfg->tcbwtable[i]; 1373 buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i]; 1374 offset++; 1375 } 1376 } 1377 1378 /** 1379 * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV 1380 * @tlv: Fill PFC TLV in IEEE format 1381 * @dcbcfg: Local store which holds the PFC CFG data 1382 */ 1383 static void 1384 ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1385 { 1386 u8 *buf = tlv->tlvinfo; 1387 u32 ouisubtype; 1388 u16 typelen; 1389 1390 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1391 ICE_DSCP_PFC_TLV_LEN); 1392 tlv->typelen = htons(typelen); 1393 1394 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 1395 ICE_DSCP_SUBTYPE_PFC); 1396 tlv->ouisubtype = htonl(ouisubtype); 1397 1398 buf[0] = dcbcfg->pfc.pfccap & 0xF; 1399 buf[1] = dcbcfg->pfc.pfcena; 1400 } 1401 1402 /** 1403 * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs 1404 * @tlv: Fill TLV data in IEEE format 1405 * @dcbcfg: Local store which holds the DCB Config 1406 * @tlvid: Type of IEEE TLV 1407 * 1408 * Add tlv information 1409 */ 1410 static void 1411 ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg, 1412 u16 tlvid) 1413 { 1414 if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) { 1415 switch (tlvid) { 1416 case ICE_IEEE_TLV_ID_ETS_CFG: 1417 ice_add_ieee_ets_tlv(tlv, dcbcfg); 1418 break; 1419 case ICE_IEEE_TLV_ID_ETS_REC: 1420 ice_add_ieee_etsrec_tlv(tlv, dcbcfg); 1421 break; 1422 case ICE_IEEE_TLV_ID_PFC_CFG: 1423 ice_add_ieee_pfc_tlv(tlv, dcbcfg); 1424 break; 1425 case ICE_IEEE_TLV_ID_APP_PRI: 1426 ice_add_ieee_app_pri_tlv(tlv, dcbcfg); 1427 break; 1428 default: 1429 break; 1430 } 1431 } else { 1432 /* pfc_mode == ICE_QOS_MODE_DSCP */ 1433 switch (tlvid) { 1434 case ICE_TLV_ID_DSCP_UP: 1435 ice_add_dscp_up_tlv(tlv, dcbcfg); 1436 break; 1437 case ICE_TLV_ID_DSCP_ENF: 1438 ice_add_dscp_enf_tlv(tlv); 1439 break; 1440 case ICE_TLV_ID_DSCP_TC_BW: 1441 ice_add_dscp_tc_bw_tlv(tlv, dcbcfg); 1442 break; 1443 case ICE_TLV_ID_DSCP_TO_PFC: 1444 ice_add_dscp_pfc_tlv(tlv, dcbcfg); 1445 break; 1446 default: 1447 break; 1448 } 1449 } 1450 } 1451 1452 /** 1453 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format 1454 * @lldpmib: pointer to the HW struct 1455 * @miblen: length of LLDP MIB 1456 * @dcbcfg: Local store which holds the DCB Config 1457 * 1458 * Convert the DCB configuration to MIB format 1459 */ 1460 static void 1461 ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) 1462 { 1463 u16 len, offset = 0, tlvid = ICE_TLV_ID_START; 1464 struct ice_lldp_org_tlv *tlv; 1465 u16 typelen; 1466 1467 tlv = (struct ice_lldp_org_tlv *)lldpmib; 1468 while (1) { 1469 ice_add_dcb_tlv(tlv, dcbcfg, tlvid++); 1470 typelen = ntohs(tlv->typelen); 1471 len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); 1472 if (len) 1473 offset += len + 2; 1474 /* END TLV or beyond LLDPDU size */ 1475 if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU || 1476 offset > ICE_LLDPDU_SIZE) 1477 break; 1478 /* Move to next TLV */ 1479 if (len) 1480 tlv = (struct ice_lldp_org_tlv *) 1481 ((char *)tlv + sizeof(tlv->typelen) + len); 1482 } 1483 *miblen = offset; 1484 } 1485 1486 /** 1487 * ice_set_dcb_cfg - Set the local LLDP MIB to FW 1488 * @pi: port information structure 1489 * 1490 * Set DCB configuration to the Firmware 1491 */ 1492 int ice_set_dcb_cfg(struct ice_port_info *pi) 1493 { 1494 u8 mib_type, *lldpmib = NULL; 1495 struct ice_dcbx_cfg *dcbcfg; 1496 struct ice_hw *hw; 1497 u16 miblen; 1498 int ret; 1499 1500 if (!pi) 1501 return -EINVAL; 1502 1503 hw = pi->hw; 1504 1505 /* update the HW local config */ 1506 dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 1507 /* Allocate the LLDPDU */ 1508 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL); 1509 if (!lldpmib) 1510 return -ENOMEM; 1511 1512 mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB; 1513 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 1514 mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING; 1515 1516 ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg); 1517 ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, 1518 NULL); 1519 1520 devm_kfree(ice_hw_to_dev(hw), lldpmib); 1521 1522 return ret; 1523 } 1524 1525 /** 1526 * ice_aq_query_port_ets - query port ETS configuration 1527 * @pi: port information structure 1528 * @buf: pointer to buffer 1529 * @buf_size: buffer size in bytes 1530 * @cd: pointer to command details structure or NULL 1531 * 1532 * query current port ETS configuration 1533 */ 1534 static int 1535 ice_aq_query_port_ets(struct ice_port_info *pi, 1536 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1537 struct ice_sq_cd *cd) 1538 { 1539 struct ice_aqc_query_port_ets *cmd; 1540 struct ice_aq_desc desc; 1541 int status; 1542 1543 if (!pi) 1544 return -EINVAL; 1545 cmd = &desc.params.port_ets; 1546 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets); 1547 cmd->port_teid = pi->root->info.node_teid; 1548 1549 status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd); 1550 return status; 1551 } 1552 1553 /** 1554 * ice_update_port_tc_tree_cfg - update TC tree configuration 1555 * @pi: port information structure 1556 * @buf: pointer to buffer 1557 * 1558 * update the SW DB with the new TC changes 1559 */ 1560 static int 1561 ice_update_port_tc_tree_cfg(struct ice_port_info *pi, 1562 struct ice_aqc_port_ets_elem *buf) 1563 { 1564 struct ice_sched_node *node, *tc_node; 1565 struct ice_aqc_txsched_elem_data elem; 1566 u32 teid1, teid2; 1567 int status = 0; 1568 u8 i, j; 1569 1570 if (!pi) 1571 return -EINVAL; 1572 /* suspend the missing TC nodes */ 1573 for (i = 0; i < pi->root->num_children; i++) { 1574 teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid); 1575 ice_for_each_traffic_class(j) { 1576 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1577 if (teid1 == teid2) 1578 break; 1579 } 1580 if (j < ICE_MAX_TRAFFIC_CLASS) 1581 continue; 1582 /* TC is missing */ 1583 pi->root->children[i]->in_use = false; 1584 } 1585 /* add the new TC nodes */ 1586 ice_for_each_traffic_class(j) { 1587 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1588 if (teid2 == ICE_INVAL_TEID) 1589 continue; 1590 /* Is it already present in the tree ? */ 1591 for (i = 0; i < pi->root->num_children; i++) { 1592 tc_node = pi->root->children[i]; 1593 if (!tc_node) 1594 continue; 1595 teid1 = le32_to_cpu(tc_node->info.node_teid); 1596 if (teid1 == teid2) { 1597 tc_node->tc_num = j; 1598 tc_node->in_use = true; 1599 break; 1600 } 1601 } 1602 if (i < pi->root->num_children) 1603 continue; 1604 /* new TC */ 1605 status = ice_sched_query_elem(pi->hw, teid2, &elem); 1606 if (!status) 1607 status = ice_sched_add_node(pi, 1, &elem, NULL); 1608 if (status) 1609 break; 1610 /* update the TC number */ 1611 node = ice_sched_find_node_by_teid(pi->root, teid2); 1612 if (node) 1613 node->tc_num = j; 1614 } 1615 return status; 1616 } 1617 1618 /** 1619 * ice_query_port_ets - query port ETS configuration 1620 * @pi: port information structure 1621 * @buf: pointer to buffer 1622 * @buf_size: buffer size in bytes 1623 * @cd: pointer to command details structure or NULL 1624 * 1625 * query current port ETS configuration and update the 1626 * SW DB with the TC changes 1627 */ 1628 int 1629 ice_query_port_ets(struct ice_port_info *pi, 1630 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1631 struct ice_sq_cd *cd) 1632 { 1633 int status; 1634 1635 mutex_lock(&pi->sched_lock); 1636 status = ice_aq_query_port_ets(pi, buf, buf_size, cd); 1637 if (!status) 1638 status = ice_update_port_tc_tree_cfg(pi, buf); 1639 mutex_unlock(&pi->sched_lock); 1640 return status; 1641 } 1642