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