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 pi->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { 959 /* Get current DCBX configuration */ 960 ret = ice_get_dcb_cfg(pi); 961 pi->is_sw_lldp = (hw->adminq.sq_last_status == ICE_AQ_RC_EPERM); 962 if (ret) 963 return ret; 964 } else if (pi->dcbx_status == ICE_DCBX_STATUS_DIS) { 965 return ICE_ERR_NOT_READY; 966 } 967 968 /* Configure the LLDP MIB change event */ 969 ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL); 970 if (!ret) 971 pi->is_sw_lldp = false; 972 973 return ret; 974 } 975 976 /** 977 * ice_add_ieee_ets_common_tlv 978 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data 979 * @ets_cfg: Container for ice_dcb_ets_cfg data 980 * 981 * Populate the TLV buffer with ice_dcb_ets_cfg data 982 */ 983 static void 984 ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 985 { 986 u8 priority0, priority1; 987 u8 offset = 0; 988 int i; 989 990 /* Priority Assignment Table (4 octets) 991 * Octets:| 1 | 2 | 3 | 4 | 992 * ----------------------------------------- 993 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 994 * ----------------------------------------- 995 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 996 * ----------------------------------------- 997 */ 998 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 999 priority0 = ets_cfg->prio_table[i * 2] & 0xF; 1000 priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF; 1001 buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1; 1002 offset++; 1003 } 1004 1005 /* TC Bandwidth Table (8 octets) 1006 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1007 * --------------------------------- 1008 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1009 * --------------------------------- 1010 * 1011 * TSA Assignment Table (8 octets) 1012 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1013 * --------------------------------- 1014 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1015 * --------------------------------- 1016 */ 1017 ice_for_each_traffic_class(i) { 1018 buf[offset] = ets_cfg->tcbwtable[i]; 1019 buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i]; 1020 offset++; 1021 } 1022 } 1023 1024 /** 1025 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 1026 * @tlv: Fill the ETS config data in IEEE format 1027 * @dcbcfg: Local store which holds the DCB Config 1028 * 1029 * Prepare IEEE 802.1Qaz ETS CFG TLV 1030 */ 1031 static void 1032 ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1033 { 1034 struct ice_dcb_ets_cfg *etscfg; 1035 u8 *buf = tlv->tlvinfo; 1036 u8 maxtcwilling = 0; 1037 u32 ouisubtype; 1038 u16 typelen; 1039 1040 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1041 ICE_IEEE_ETS_TLV_LEN); 1042 tlv->typelen = htons(typelen); 1043 1044 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1045 ICE_IEEE_SUBTYPE_ETS_CFG); 1046 tlv->ouisubtype = htonl(ouisubtype); 1047 1048 /* First Octet post subtype 1049 * -------------------------- 1050 * |will-|CBS | Re- | Max | 1051 * |ing | |served| TCs | 1052 * -------------------------- 1053 * |1bit | 1bit|3 bits|3bits| 1054 */ 1055 etscfg = &dcbcfg->etscfg; 1056 if (etscfg->willing) 1057 maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S); 1058 maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 1059 buf[0] = maxtcwilling; 1060 1061 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1062 ice_add_ieee_ets_common_tlv(&buf[1], etscfg); 1063 } 1064 1065 /** 1066 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 1067 * @tlv: Fill ETS Recommended TLV in IEEE format 1068 * @dcbcfg: Local store which holds the DCB Config 1069 * 1070 * Prepare IEEE 802.1Qaz ETS REC TLV 1071 */ 1072 static void 1073 ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 1074 struct ice_dcbx_cfg *dcbcfg) 1075 { 1076 struct ice_dcb_ets_cfg *etsrec; 1077 u8 *buf = tlv->tlvinfo; 1078 u32 ouisubtype; 1079 u16 typelen; 1080 1081 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1082 ICE_IEEE_ETS_TLV_LEN); 1083 tlv->typelen = htons(typelen); 1084 1085 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1086 ICE_IEEE_SUBTYPE_ETS_REC); 1087 tlv->ouisubtype = htonl(ouisubtype); 1088 1089 etsrec = &dcbcfg->etsrec; 1090 1091 /* First Octet is reserved */ 1092 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1093 ice_add_ieee_ets_common_tlv(&buf[1], etsrec); 1094 } 1095 1096 /** 1097 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 1098 * @tlv: Fill PFC TLV in IEEE format 1099 * @dcbcfg: Local store which holds the PFC CFG data 1100 * 1101 * Prepare IEEE 802.1Qaz PFC CFG TLV 1102 */ 1103 static void 1104 ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1105 { 1106 u8 *buf = tlv->tlvinfo; 1107 u32 ouisubtype; 1108 u16 typelen; 1109 1110 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1111 ICE_IEEE_PFC_TLV_LEN); 1112 tlv->typelen = htons(typelen); 1113 1114 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1115 ICE_IEEE_SUBTYPE_PFC_CFG); 1116 tlv->ouisubtype = htonl(ouisubtype); 1117 1118 /* ---------------------------------------- 1119 * |will-|MBC | Re- | PFC | PFC Enable | 1120 * |ing | |served| cap | | 1121 * ----------------------------------------- 1122 * |1bit | 1bit|2 bits|4bits| 1 octet | 1123 */ 1124 if (dcbcfg->pfc.willing) 1125 buf[0] = BIT(ICE_IEEE_PFC_WILLING_S); 1126 1127 if (dcbcfg->pfc.mbc) 1128 buf[0] |= BIT(ICE_IEEE_PFC_MBC_S); 1129 1130 buf[0] |= dcbcfg->pfc.pfccap & 0xF; 1131 buf[1] = dcbcfg->pfc.pfcena; 1132 } 1133 1134 /** 1135 * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 1136 * @tlv: Fill APP TLV in IEEE format 1137 * @dcbcfg: Local store which holds the APP CFG data 1138 * 1139 * Prepare IEEE 802.1Qaz APP CFG TLV 1140 */ 1141 static void 1142 ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv, 1143 struct ice_dcbx_cfg *dcbcfg) 1144 { 1145 u16 typelen, len, offset = 0; 1146 u8 priority, selector, i = 0; 1147 u8 *buf = tlv->tlvinfo; 1148 u32 ouisubtype; 1149 1150 /* No APP TLVs then just return */ 1151 if (dcbcfg->numapps == 0) 1152 return; 1153 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1154 ICE_IEEE_SUBTYPE_APP_PRI); 1155 tlv->ouisubtype = htonl(ouisubtype); 1156 1157 /* Move offset to App Priority Table */ 1158 offset++; 1159 /* Application Priority Table (3 octets) 1160 * Octets:| 1 | 2 | 3 | 1161 * ----------------------------------------- 1162 * |Priority|Rsrvd| Sel | Protocol ID | 1163 * ----------------------------------------- 1164 * Bits:|23 21|20 19|18 16|15 0| 1165 * ----------------------------------------- 1166 */ 1167 while (i < dcbcfg->numapps) { 1168 priority = dcbcfg->app[i].priority & 0x7; 1169 selector = dcbcfg->app[i].selector & 0x7; 1170 buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector; 1171 buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF; 1172 buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF; 1173 /* Move to next app */ 1174 offset += 3; 1175 i++; 1176 if (i >= ICE_DCBX_MAX_APPS) 1177 break; 1178 } 1179 /* len includes size of ouisubtype + 1 reserved + 3*numapps */ 1180 len = sizeof(tlv->ouisubtype) + 1 + (i * 3); 1181 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF)); 1182 tlv->typelen = htons(typelen); 1183 } 1184 1185 /** 1186 * ice_add_dcb_tlv - Add all IEEE TLVs 1187 * @tlv: Fill TLV data in IEEE format 1188 * @dcbcfg: Local store which holds the DCB Config 1189 * @tlvid: Type of IEEE TLV 1190 * 1191 * Add tlv information 1192 */ 1193 static void 1194 ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg, 1195 u16 tlvid) 1196 { 1197 switch (tlvid) { 1198 case ICE_IEEE_TLV_ID_ETS_CFG: 1199 ice_add_ieee_ets_tlv(tlv, dcbcfg); 1200 break; 1201 case ICE_IEEE_TLV_ID_ETS_REC: 1202 ice_add_ieee_etsrec_tlv(tlv, dcbcfg); 1203 break; 1204 case ICE_IEEE_TLV_ID_PFC_CFG: 1205 ice_add_ieee_pfc_tlv(tlv, dcbcfg); 1206 break; 1207 case ICE_IEEE_TLV_ID_APP_PRI: 1208 ice_add_ieee_app_pri_tlv(tlv, dcbcfg); 1209 break; 1210 default: 1211 break; 1212 } 1213 } 1214 1215 /** 1216 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format 1217 * @lldpmib: pointer to the HW struct 1218 * @miblen: length of LLDP MIB 1219 * @dcbcfg: Local store which holds the DCB Config 1220 * 1221 * Convert the DCB configuration to MIB format 1222 */ 1223 static void 1224 ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) 1225 { 1226 u16 len, offset = 0, tlvid = ICE_TLV_ID_START; 1227 struct ice_lldp_org_tlv *tlv; 1228 u16 typelen; 1229 1230 tlv = (struct ice_lldp_org_tlv *)lldpmib; 1231 while (1) { 1232 ice_add_dcb_tlv(tlv, dcbcfg, tlvid++); 1233 typelen = ntohs(tlv->typelen); 1234 len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S; 1235 if (len) 1236 offset += len + 2; 1237 /* END TLV or beyond LLDPDU size */ 1238 if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU || 1239 offset > ICE_LLDPDU_SIZE) 1240 break; 1241 /* Move to next TLV */ 1242 if (len) 1243 tlv = (struct ice_lldp_org_tlv *) 1244 ((char *)tlv + sizeof(tlv->typelen) + len); 1245 } 1246 *miblen = offset; 1247 } 1248 1249 /** 1250 * ice_set_dcb_cfg - Set the local LLDP MIB to FW 1251 * @pi: port information structure 1252 * 1253 * Set DCB configuration to the Firmware 1254 */ 1255 enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi) 1256 { 1257 u8 mib_type, *lldpmib = NULL; 1258 struct ice_dcbx_cfg *dcbcfg; 1259 enum ice_status ret; 1260 struct ice_hw *hw; 1261 u16 miblen; 1262 1263 if (!pi) 1264 return ICE_ERR_PARAM; 1265 1266 hw = pi->hw; 1267 1268 /* update the HW local config */ 1269 dcbcfg = &pi->local_dcbx_cfg; 1270 /* Allocate the LLDPDU */ 1271 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL); 1272 if (!lldpmib) 1273 return ICE_ERR_NO_MEMORY; 1274 1275 mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB; 1276 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 1277 mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING; 1278 1279 ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg); 1280 ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, 1281 NULL); 1282 1283 devm_kfree(ice_hw_to_dev(hw), lldpmib); 1284 1285 return ret; 1286 } 1287 1288 /** 1289 * ice_aq_query_port_ets - query port ets configuration 1290 * @pi: port information structure 1291 * @buf: pointer to buffer 1292 * @buf_size: buffer size in bytes 1293 * @cd: pointer to command details structure or NULL 1294 * 1295 * query current port ets configuration 1296 */ 1297 static enum ice_status 1298 ice_aq_query_port_ets(struct ice_port_info *pi, 1299 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1300 struct ice_sq_cd *cd) 1301 { 1302 struct ice_aqc_query_port_ets *cmd; 1303 struct ice_aq_desc desc; 1304 enum ice_status status; 1305 1306 if (!pi) 1307 return ICE_ERR_PARAM; 1308 cmd = &desc.params.port_ets; 1309 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets); 1310 cmd->port_teid = pi->root->info.node_teid; 1311 1312 status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd); 1313 return status; 1314 } 1315 1316 /** 1317 * ice_update_port_tc_tree_cfg - update TC tree configuration 1318 * @pi: port information structure 1319 * @buf: pointer to buffer 1320 * 1321 * update the SW DB with the new TC changes 1322 */ 1323 static enum ice_status 1324 ice_update_port_tc_tree_cfg(struct ice_port_info *pi, 1325 struct ice_aqc_port_ets_elem *buf) 1326 { 1327 struct ice_sched_node *node, *tc_node; 1328 struct ice_aqc_get_elem elem; 1329 enum ice_status status = 0; 1330 u32 teid1, teid2; 1331 u8 i, j; 1332 1333 if (!pi) 1334 return ICE_ERR_PARAM; 1335 /* suspend the missing TC nodes */ 1336 for (i = 0; i < pi->root->num_children; i++) { 1337 teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid); 1338 ice_for_each_traffic_class(j) { 1339 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1340 if (teid1 == teid2) 1341 break; 1342 } 1343 if (j < ICE_MAX_TRAFFIC_CLASS) 1344 continue; 1345 /* TC is missing */ 1346 pi->root->children[i]->in_use = false; 1347 } 1348 /* add the new TC nodes */ 1349 ice_for_each_traffic_class(j) { 1350 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1351 if (teid2 == ICE_INVAL_TEID) 1352 continue; 1353 /* Is it already present in the tree ? */ 1354 for (i = 0; i < pi->root->num_children; i++) { 1355 tc_node = pi->root->children[i]; 1356 if (!tc_node) 1357 continue; 1358 teid1 = le32_to_cpu(tc_node->info.node_teid); 1359 if (teid1 == teid2) { 1360 tc_node->tc_num = j; 1361 tc_node->in_use = true; 1362 break; 1363 } 1364 } 1365 if (i < pi->root->num_children) 1366 continue; 1367 /* new TC */ 1368 status = ice_sched_query_elem(pi->hw, teid2, &elem); 1369 if (!status) 1370 status = ice_sched_add_node(pi, 1, &elem.generic[0]); 1371 if (status) 1372 break; 1373 /* update the TC number */ 1374 node = ice_sched_find_node_by_teid(pi->root, teid2); 1375 if (node) 1376 node->tc_num = j; 1377 } 1378 return status; 1379 } 1380 1381 /** 1382 * ice_query_port_ets - query port ets configuration 1383 * @pi: port information structure 1384 * @buf: pointer to buffer 1385 * @buf_size: buffer size in bytes 1386 * @cd: pointer to command details structure or NULL 1387 * 1388 * query current port ets configuration and update the 1389 * SW DB with the TC changes 1390 */ 1391 enum ice_status 1392 ice_query_port_ets(struct ice_port_info *pi, 1393 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1394 struct ice_sq_cd *cd) 1395 { 1396 enum ice_status status; 1397 1398 mutex_lock(&pi->sched_lock); 1399 status = ice_aq_query_port_ets(pi, buf, buf_size, cd); 1400 if (!status) 1401 status = ice_update_port_tc_tree_cfg(pi, buf); 1402 mutex_unlock(&pi->sched_lock); 1403 return status; 1404 } 1405