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