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