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