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