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