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 static 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 if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT) 451 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 452 else 453 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 454 } 455 456 /* Number of TCs supported (1 octet) */ 457 etscfg->maxtcs = buf[offset]; 458 } 459 460 /** 461 * ice_parse_cee_pfccfg_tlv 462 * @tlv: CEE DCBX PFC CFG TLV 463 * @dcbcfg: Local store to update PFC CFG data 464 * 465 * Parses CEE DCBX PFC CFG TLV 466 */ 467 static void 468 ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv, 469 struct ice_dcbx_cfg *dcbcfg) 470 { 471 u8 *buf = tlv->tlvinfo; 472 473 if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M) 474 dcbcfg->pfc.willing = 1; 475 476 /* ------------------------ 477 * | PFC Enable | PFC TCs | 478 * ------------------------ 479 * | 1 octet | 1 octet | 480 */ 481 dcbcfg->pfc.pfcena = buf[0]; 482 dcbcfg->pfc.pfccap = buf[1]; 483 } 484 485 /** 486 * ice_parse_cee_app_tlv 487 * @tlv: CEE DCBX APP TLV 488 * @dcbcfg: Local store to update APP PRIO data 489 * 490 * Parses CEE DCBX APP PRIO TLV 491 */ 492 static void 493 ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 494 { 495 u16 len, typelen, offset = 0; 496 struct ice_cee_app_prio *app; 497 u8 i; 498 499 typelen = ntohs(tlv->hdr.typelen); 500 len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 501 502 dcbcfg->numapps = len / sizeof(*app); 503 if (!dcbcfg->numapps) 504 return; 505 if (dcbcfg->numapps > ICE_DCBX_MAX_APPS) 506 dcbcfg->numapps = ICE_DCBX_MAX_APPS; 507 508 for (i = 0; i < dcbcfg->numapps; i++) { 509 u8 up, selector; 510 511 app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset); 512 for (up = 0; up < ICE_MAX_USER_PRIORITY; up++) 513 if (app->prio_map & BIT(up)) 514 break; 515 516 dcbcfg->app[i].priority = up; 517 518 /* Get Selector from lower 2 bits, and convert to IEEE */ 519 selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M); 520 switch (selector) { 521 case ICE_CEE_APP_SEL_ETHTYPE: 522 dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE; 523 break; 524 case ICE_CEE_APP_SEL_TCPIP: 525 dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP; 526 break; 527 default: 528 /* Keep selector as it is for unknown types */ 529 dcbcfg->app[i].selector = selector; 530 } 531 532 dcbcfg->app[i].prot_id = ntohs(app->protocol); 533 /* Move to next app */ 534 offset += sizeof(*app); 535 } 536 } 537 538 /** 539 * ice_parse_cee_tlv 540 * @tlv: CEE DCBX TLV 541 * @dcbcfg: Local store to update DCBX config data 542 * 543 * Get the TLV subtype and send it to parsing function 544 * based on the subtype value 545 */ 546 static void 547 ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 548 { 549 struct ice_cee_feat_tlv *sub_tlv; 550 u8 subtype, feat_tlv_count = 0; 551 u16 len, tlvlen, typelen; 552 u32 ouisubtype; 553 554 ouisubtype = ntohl(tlv->ouisubtype); 555 subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >> 556 ICE_LLDP_TLV_SUBTYPE_S); 557 /* Return if not CEE DCBX */ 558 if (subtype != ICE_CEE_DCBX_TYPE) 559 return; 560 561 typelen = ntohs(tlv->typelen); 562 tlvlen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 563 len = sizeof(tlv->typelen) + sizeof(ouisubtype) + 564 sizeof(struct ice_cee_ctrl_tlv); 565 /* Return if no CEE DCBX Feature TLVs */ 566 if (tlvlen <= len) 567 return; 568 569 sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len); 570 while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) { 571 u16 sublen; 572 573 typelen = ntohs(sub_tlv->hdr.typelen); 574 sublen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 575 subtype = (u8)((typelen & ICE_LLDP_TLV_TYPE_M) >> 576 ICE_LLDP_TLV_TYPE_S); 577 switch (subtype) { 578 case ICE_CEE_SUBTYPE_PG_CFG: 579 ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); 580 break; 581 case ICE_CEE_SUBTYPE_PFC_CFG: 582 ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); 583 break; 584 case ICE_CEE_SUBTYPE_APP_PRI: 585 ice_parse_cee_app_tlv(sub_tlv, dcbcfg); 586 break; 587 default: 588 return; /* Invalid Sub-type return */ 589 } 590 feat_tlv_count++; 591 /* Move to next sub TLV */ 592 sub_tlv = (struct ice_cee_feat_tlv *) 593 ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) + 594 sublen); 595 } 596 } 597 598 /** 599 * ice_parse_org_tlv 600 * @tlv: Organization specific TLV 601 * @dcbcfg: Local store to update ETS REC data 602 * 603 * Currently only IEEE 802.1Qaz TLV is supported, all others 604 * will be returned 605 */ 606 static void 607 ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 608 { 609 u32 ouisubtype; 610 u32 oui; 611 612 ouisubtype = ntohl(tlv->ouisubtype); 613 oui = ((ouisubtype & ICE_LLDP_TLV_OUI_M) >> ICE_LLDP_TLV_OUI_S); 614 switch (oui) { 615 case ICE_IEEE_8021QAZ_OUI: 616 ice_parse_ieee_tlv(tlv, dcbcfg); 617 break; 618 case ICE_CEE_DCBX_OUI: 619 ice_parse_cee_tlv(tlv, dcbcfg); 620 break; 621 default: 622 break; 623 } 624 } 625 626 /** 627 * ice_lldp_to_dcb_cfg 628 * @lldpmib: LLDPDU to be parsed 629 * @dcbcfg: store for LLDPDU data 630 * 631 * Parse DCB configuration from the LLDPDU 632 */ 633 static enum ice_status 634 ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg) 635 { 636 struct ice_lldp_org_tlv *tlv; 637 enum ice_status ret = 0; 638 u16 offset = 0; 639 u16 typelen; 640 u16 type; 641 u16 len; 642 643 if (!lldpmib || !dcbcfg) 644 return ICE_ERR_PARAM; 645 646 /* set to the start of LLDPDU */ 647 lldpmib += ETH_HLEN; 648 tlv = (struct ice_lldp_org_tlv *)lldpmib; 649 while (1) { 650 typelen = ntohs(tlv->typelen); 651 type = ((typelen & ICE_LLDP_TLV_TYPE_M) >> ICE_LLDP_TLV_TYPE_S); 652 len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 653 offset += sizeof(typelen) + len; 654 655 /* END TLV or beyond LLDPDU size */ 656 if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE) 657 break; 658 659 switch (type) { 660 case ICE_TLV_TYPE_ORG: 661 ice_parse_org_tlv(tlv, dcbcfg); 662 break; 663 default: 664 break; 665 } 666 667 /* Move to next TLV */ 668 tlv = (struct ice_lldp_org_tlv *) 669 ((char *)tlv + sizeof(tlv->typelen) + len); 670 } 671 672 return ret; 673 } 674 675 /** 676 * ice_aq_get_dcb_cfg 677 * @hw: pointer to the HW struct 678 * @mib_type: MIB type for the query 679 * @bridgetype: bridge type for the query (remote) 680 * @dcbcfg: store for LLDPDU data 681 * 682 * Query DCB configuration from the firmware 683 */ 684 enum ice_status 685 ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype, 686 struct ice_dcbx_cfg *dcbcfg) 687 { 688 enum ice_status ret; 689 u8 *lldpmib; 690 691 /* Allocate the LLDPDU */ 692 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL); 693 if (!lldpmib) 694 return ICE_ERR_NO_MEMORY; 695 696 ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib, 697 ICE_LLDPDU_SIZE, NULL, NULL, NULL); 698 699 if (!ret) 700 /* Parse LLDP MIB to get DCB configuration */ 701 ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg); 702 703 devm_kfree(ice_hw_to_dev(hw), lldpmib); 704 705 return ret; 706 } 707 708 /** 709 * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW 710 * @hw: pointer to the HW struct 711 * @start_dcbx_agent: True if DCBX Agent needs to be started 712 * False if DCBX Agent needs to be stopped 713 * @dcbx_agent_status: FW indicates back the DCBX agent status 714 * True if DCBX Agent is active 715 * False if DCBX Agent is stopped 716 * @cd: pointer to command details structure or NULL 717 * 718 * Start/Stop the embedded dcbx Agent. In case that this wrapper function 719 * returns ICE_SUCCESS, caller will need to check if FW returns back the same 720 * value as stated in dcbx_agent_status, and react accordingly. (0x0A09) 721 */ 722 enum ice_status 723 ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent, 724 bool *dcbx_agent_status, struct ice_sq_cd *cd) 725 { 726 struct ice_aqc_lldp_stop_start_specific_agent *cmd; 727 enum ice_status status; 728 struct ice_aq_desc desc; 729 u16 opcode; 730 731 cmd = &desc.params.lldp_agent_ctrl; 732 733 opcode = ice_aqc_opc_lldp_stop_start_specific_agent; 734 735 ice_fill_dflt_direct_cmd_desc(&desc, opcode); 736 737 if (start_dcbx_agent) 738 cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX; 739 740 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 741 742 *dcbx_agent_status = false; 743 744 if (!status && 745 cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX) 746 *dcbx_agent_status = true; 747 748 return status; 749 } 750 751 /** 752 * ice_aq_get_cee_dcb_cfg 753 * @hw: pointer to the HW struct 754 * @buff: response buffer that stores CEE operational configuration 755 * @cd: pointer to command details structure or NULL 756 * 757 * Get CEE DCBX mode operational configuration from firmware (0x0A07) 758 */ 759 static enum ice_status 760 ice_aq_get_cee_dcb_cfg(struct ice_hw *hw, 761 struct ice_aqc_get_cee_dcb_cfg_resp *buff, 762 struct ice_sq_cd *cd) 763 { 764 struct ice_aq_desc desc; 765 766 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg); 767 768 return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd); 769 } 770 771 /** 772 * ice_cee_to_dcb_cfg 773 * @cee_cfg: pointer to CEE configuration struct 774 * @dcbcfg: DCB configuration struct 775 * 776 * Convert CEE configuration from firmware to DCB configuration 777 */ 778 static void 779 ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, 780 struct ice_dcbx_cfg *dcbcfg) 781 { 782 u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); 783 u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift; 784 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); 785 u8 i, err, sync, oper, app_index, ice_app_sel_type; 786 u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; 787 u16 ice_app_prot_id_type; 788 789 /* CEE PG data to ETS config */ 790 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 791 792 /* Note that the FW creates the oper_prio_tc nibbles reversed 793 * from those in the CEE Priority Group sub-TLV. 794 */ 795 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 796 dcbcfg->etscfg.prio_table[i * 2] = 797 ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_0_M) >> 798 ICE_CEE_PGID_PRIO_0_S); 799 dcbcfg->etscfg.prio_table[i * 2 + 1] = 800 ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_1_M) >> 801 ICE_CEE_PGID_PRIO_1_S); 802 } 803 804 ice_for_each_traffic_class(i) { 805 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 806 807 if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) { 808 /* Map it to next empty TC */ 809 dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1; 810 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 811 } else { 812 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 813 } 814 } 815 816 /* CEE PFC data to ETS config */ 817 dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en; 818 dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS; 819 820 app_index = 0; 821 for (i = 0; i < 3; i++) { 822 if (i == 0) { 823 /* FCoE APP */ 824 ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M; 825 ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S; 826 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M; 827 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S; 828 ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 829 ice_app_prot_id_type = ICE_APP_PROT_ID_FCOE; 830 } else if (i == 1) { 831 /* iSCSI APP */ 832 ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M; 833 ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S; 834 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M; 835 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S; 836 ice_app_sel_type = ICE_APP_SEL_TCPIP; 837 ice_app_prot_id_type = ICE_APP_PROT_ID_ISCSI; 838 } else { 839 /* FIP APP */ 840 ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M; 841 ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S; 842 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M; 843 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S; 844 ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 845 ice_app_prot_id_type = ICE_APP_PROT_ID_FIP; 846 } 847 848 status = (tlv_status & ice_aqc_cee_status_mask) >> 849 ice_aqc_cee_status_shift; 850 err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0; 851 sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0; 852 oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0; 853 /* Add FCoE/iSCSI/FIP APP if Error is False and 854 * Oper/Sync is True 855 */ 856 if (!err && sync && oper) { 857 dcbcfg->app[app_index].priority = 858 (app_prio & ice_aqc_cee_app_mask) >> 859 ice_aqc_cee_app_shift; 860 dcbcfg->app[app_index].selector = ice_app_sel_type; 861 dcbcfg->app[app_index].prot_id = ice_app_prot_id_type; 862 app_index++; 863 } 864 } 865 866 dcbcfg->numapps = app_index; 867 } 868 869 /** 870 * ice_get_ieee_dcb_cfg 871 * @pi: port information structure 872 * @dcbx_mode: mode of DCBX (IEEE or CEE) 873 * 874 * Get IEEE or CEE mode DCB configuration from the Firmware 875 */ 876 static enum ice_status 877 ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode) 878 { 879 struct ice_dcbx_cfg *dcbx_cfg = NULL; 880 enum ice_status ret; 881 882 if (!pi) 883 return ICE_ERR_PARAM; 884 885 if (dcbx_mode == ICE_DCBX_MODE_IEEE) 886 dcbx_cfg = &pi->local_dcbx_cfg; 887 else if (dcbx_mode == ICE_DCBX_MODE_CEE) 888 dcbx_cfg = &pi->desired_dcbx_cfg; 889 890 /* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE 891 * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE 892 */ 893 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL, 894 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 895 if (ret) 896 goto out; 897 898 /* Get Remote DCB Config */ 899 dcbx_cfg = &pi->remote_dcbx_cfg; 900 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE, 901 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 902 /* Don't treat ENOENT as an error for Remote MIBs */ 903 if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 904 ret = 0; 905 906 out: 907 return ret; 908 } 909 910 /** 911 * ice_get_dcb_cfg 912 * @pi: port information structure 913 * 914 * Get DCB configuration from the Firmware 915 */ 916 enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi) 917 { 918 struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg; 919 struct ice_dcbx_cfg *dcbx_cfg; 920 enum ice_status ret; 921 922 if (!pi) 923 return ICE_ERR_PARAM; 924 925 ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL); 926 if (!ret) { 927 /* CEE mode */ 928 dcbx_cfg = &pi->local_dcbx_cfg; 929 dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_CEE; 930 dcbx_cfg->tlv_status = le32_to_cpu(cee_cfg.tlv_status); 931 ice_cee_to_dcb_cfg(&cee_cfg, dcbx_cfg); 932 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE); 933 } else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) { 934 /* CEE mode not enabled try querying IEEE data */ 935 dcbx_cfg = &pi->local_dcbx_cfg; 936 dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE; 937 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE); 938 } 939 940 return ret; 941 } 942 943 /** 944 * ice_init_dcb 945 * @hw: pointer to the HW struct 946 * @enable_mib_change: enable MIB change event 947 * 948 * Update DCB configuration from the Firmware 949 */ 950 enum ice_status ice_init_dcb(struct ice_hw *hw, bool enable_mib_change) 951 { 952 struct ice_port_info *pi = hw->port_info; 953 enum ice_status ret = 0; 954 955 if (!hw->func_caps.common_cap.dcb) 956 return ICE_ERR_NOT_SUPPORTED; 957 958 pi->is_sw_lldp = true; 959 960 /* Get DCBX status */ 961 pi->dcbx_status = ice_get_dcbx_status(hw); 962 963 if (pi->dcbx_status == ICE_DCBX_STATUS_DONE || 964 pi->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS || 965 pi->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { 966 /* Get current DCBX configuration */ 967 ret = ice_get_dcb_cfg(pi); 968 if (ret) 969 return ret; 970 pi->is_sw_lldp = false; 971 } else if (pi->dcbx_status == ICE_DCBX_STATUS_DIS) { 972 return ICE_ERR_NOT_READY; 973 } 974 975 /* Configure the LLDP MIB change event */ 976 if (enable_mib_change) { 977 ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL); 978 if (ret) 979 pi->is_sw_lldp = true; 980 } 981 982 return ret; 983 } 984 985 /** 986 * ice_cfg_lldp_mib_change 987 * @hw: pointer to the HW struct 988 * @ena_mib: enable/disable MIB change event 989 * 990 * Configure (disable/enable) MIB 991 */ 992 enum ice_status ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib) 993 { 994 struct ice_port_info *pi = hw->port_info; 995 enum ice_status ret; 996 997 if (!hw->func_caps.common_cap.dcb) 998 return ICE_ERR_NOT_SUPPORTED; 999 1000 /* Get DCBX status */ 1001 pi->dcbx_status = ice_get_dcbx_status(hw); 1002 1003 if (pi->dcbx_status == ICE_DCBX_STATUS_DIS) 1004 return ICE_ERR_NOT_READY; 1005 1006 ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL); 1007 if (!ret) 1008 pi->is_sw_lldp = !ena_mib; 1009 1010 return ret; 1011 } 1012 1013 /** 1014 * ice_add_ieee_ets_common_tlv 1015 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data 1016 * @ets_cfg: Container for ice_dcb_ets_cfg data 1017 * 1018 * Populate the TLV buffer with ice_dcb_ets_cfg data 1019 */ 1020 static void 1021 ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 1022 { 1023 u8 priority0, priority1; 1024 u8 offset = 0; 1025 int i; 1026 1027 /* Priority Assignment Table (4 octets) 1028 * Octets:| 1 | 2 | 3 | 4 | 1029 * ----------------------------------------- 1030 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 1031 * ----------------------------------------- 1032 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 1033 * ----------------------------------------- 1034 */ 1035 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 1036 priority0 = ets_cfg->prio_table[i * 2] & 0xF; 1037 priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF; 1038 buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1; 1039 offset++; 1040 } 1041 1042 /* TC Bandwidth Table (8 octets) 1043 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1044 * --------------------------------- 1045 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1046 * --------------------------------- 1047 * 1048 * TSA Assignment Table (8 octets) 1049 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1050 * --------------------------------- 1051 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 1052 * --------------------------------- 1053 */ 1054 ice_for_each_traffic_class(i) { 1055 buf[offset] = ets_cfg->tcbwtable[i]; 1056 buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i]; 1057 offset++; 1058 } 1059 } 1060 1061 /** 1062 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 1063 * @tlv: Fill the ETS config data in IEEE format 1064 * @dcbcfg: Local store which holds the DCB Config 1065 * 1066 * Prepare IEEE 802.1Qaz ETS CFG TLV 1067 */ 1068 static void 1069 ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1070 { 1071 struct ice_dcb_ets_cfg *etscfg; 1072 u8 *buf = tlv->tlvinfo; 1073 u8 maxtcwilling = 0; 1074 u32 ouisubtype; 1075 u16 typelen; 1076 1077 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1078 ICE_IEEE_ETS_TLV_LEN); 1079 tlv->typelen = htons(typelen); 1080 1081 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1082 ICE_IEEE_SUBTYPE_ETS_CFG); 1083 tlv->ouisubtype = htonl(ouisubtype); 1084 1085 /* First Octet post subtype 1086 * -------------------------- 1087 * |will-|CBS | Re- | Max | 1088 * |ing | |served| TCs | 1089 * -------------------------- 1090 * |1bit | 1bit|3 bits|3bits| 1091 */ 1092 etscfg = &dcbcfg->etscfg; 1093 if (etscfg->willing) 1094 maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S); 1095 maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 1096 buf[0] = maxtcwilling; 1097 1098 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1099 ice_add_ieee_ets_common_tlv(&buf[1], etscfg); 1100 } 1101 1102 /** 1103 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 1104 * @tlv: Fill ETS Recommended TLV in IEEE format 1105 * @dcbcfg: Local store which holds the DCB Config 1106 * 1107 * Prepare IEEE 802.1Qaz ETS REC TLV 1108 */ 1109 static void 1110 ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 1111 struct ice_dcbx_cfg *dcbcfg) 1112 { 1113 struct ice_dcb_ets_cfg *etsrec; 1114 u8 *buf = tlv->tlvinfo; 1115 u32 ouisubtype; 1116 u16 typelen; 1117 1118 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1119 ICE_IEEE_ETS_TLV_LEN); 1120 tlv->typelen = htons(typelen); 1121 1122 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1123 ICE_IEEE_SUBTYPE_ETS_REC); 1124 tlv->ouisubtype = htonl(ouisubtype); 1125 1126 etsrec = &dcbcfg->etsrec; 1127 1128 /* First Octet is reserved */ 1129 /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 1130 ice_add_ieee_ets_common_tlv(&buf[1], etsrec); 1131 } 1132 1133 /** 1134 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 1135 * @tlv: Fill PFC TLV in IEEE format 1136 * @dcbcfg: Local store which holds the PFC CFG data 1137 * 1138 * Prepare IEEE 802.1Qaz PFC CFG TLV 1139 */ 1140 static void 1141 ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 1142 { 1143 u8 *buf = tlv->tlvinfo; 1144 u32 ouisubtype; 1145 u16 typelen; 1146 1147 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 1148 ICE_IEEE_PFC_TLV_LEN); 1149 tlv->typelen = htons(typelen); 1150 1151 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1152 ICE_IEEE_SUBTYPE_PFC_CFG); 1153 tlv->ouisubtype = htonl(ouisubtype); 1154 1155 /* ---------------------------------------- 1156 * |will-|MBC | Re- | PFC | PFC Enable | 1157 * |ing | |served| cap | | 1158 * ----------------------------------------- 1159 * |1bit | 1bit|2 bits|4bits| 1 octet | 1160 */ 1161 if (dcbcfg->pfc.willing) 1162 buf[0] = BIT(ICE_IEEE_PFC_WILLING_S); 1163 1164 if (dcbcfg->pfc.mbc) 1165 buf[0] |= BIT(ICE_IEEE_PFC_MBC_S); 1166 1167 buf[0] |= dcbcfg->pfc.pfccap & 0xF; 1168 buf[1] = dcbcfg->pfc.pfcena; 1169 } 1170 1171 /** 1172 * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 1173 * @tlv: Fill APP TLV in IEEE format 1174 * @dcbcfg: Local store which holds the APP CFG data 1175 * 1176 * Prepare IEEE 802.1Qaz APP CFG TLV 1177 */ 1178 static void 1179 ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv, 1180 struct ice_dcbx_cfg *dcbcfg) 1181 { 1182 u16 typelen, len, offset = 0; 1183 u8 priority, selector, i = 0; 1184 u8 *buf = tlv->tlvinfo; 1185 u32 ouisubtype; 1186 1187 /* No APP TLVs then just return */ 1188 if (dcbcfg->numapps == 0) 1189 return; 1190 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 1191 ICE_IEEE_SUBTYPE_APP_PRI); 1192 tlv->ouisubtype = htonl(ouisubtype); 1193 1194 /* Move offset to App Priority Table */ 1195 offset++; 1196 /* Application Priority Table (3 octets) 1197 * Octets:| 1 | 2 | 3 | 1198 * ----------------------------------------- 1199 * |Priority|Rsrvd| Sel | Protocol ID | 1200 * ----------------------------------------- 1201 * Bits:|23 21|20 19|18 16|15 0| 1202 * ----------------------------------------- 1203 */ 1204 while (i < dcbcfg->numapps) { 1205 priority = dcbcfg->app[i].priority & 0x7; 1206 selector = dcbcfg->app[i].selector & 0x7; 1207 buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector; 1208 buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF; 1209 buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF; 1210 /* Move to next app */ 1211 offset += 3; 1212 i++; 1213 if (i >= ICE_DCBX_MAX_APPS) 1214 break; 1215 } 1216 /* len includes size of ouisubtype + 1 reserved + 3*numapps */ 1217 len = sizeof(tlv->ouisubtype) + 1 + (i * 3); 1218 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF)); 1219 tlv->typelen = htons(typelen); 1220 } 1221 1222 /** 1223 * ice_add_dcb_tlv - Add all IEEE TLVs 1224 * @tlv: Fill TLV data in IEEE format 1225 * @dcbcfg: Local store which holds the DCB Config 1226 * @tlvid: Type of IEEE TLV 1227 * 1228 * Add tlv information 1229 */ 1230 static void 1231 ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg, 1232 u16 tlvid) 1233 { 1234 switch (tlvid) { 1235 case ICE_IEEE_TLV_ID_ETS_CFG: 1236 ice_add_ieee_ets_tlv(tlv, dcbcfg); 1237 break; 1238 case ICE_IEEE_TLV_ID_ETS_REC: 1239 ice_add_ieee_etsrec_tlv(tlv, dcbcfg); 1240 break; 1241 case ICE_IEEE_TLV_ID_PFC_CFG: 1242 ice_add_ieee_pfc_tlv(tlv, dcbcfg); 1243 break; 1244 case ICE_IEEE_TLV_ID_APP_PRI: 1245 ice_add_ieee_app_pri_tlv(tlv, dcbcfg); 1246 break; 1247 default: 1248 break; 1249 } 1250 } 1251 1252 /** 1253 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format 1254 * @lldpmib: pointer to the HW struct 1255 * @miblen: length of LLDP MIB 1256 * @dcbcfg: Local store which holds the DCB Config 1257 * 1258 * Convert the DCB configuration to MIB format 1259 */ 1260 static void 1261 ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) 1262 { 1263 u16 len, offset = 0, tlvid = ICE_TLV_ID_START; 1264 struct ice_lldp_org_tlv *tlv; 1265 u16 typelen; 1266 1267 tlv = (struct ice_lldp_org_tlv *)lldpmib; 1268 while (1) { 1269 ice_add_dcb_tlv(tlv, dcbcfg, tlvid++); 1270 typelen = ntohs(tlv->typelen); 1271 len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S; 1272 if (len) 1273 offset += len + 2; 1274 /* END TLV or beyond LLDPDU size */ 1275 if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU || 1276 offset > ICE_LLDPDU_SIZE) 1277 break; 1278 /* Move to next TLV */ 1279 if (len) 1280 tlv = (struct ice_lldp_org_tlv *) 1281 ((char *)tlv + sizeof(tlv->typelen) + len); 1282 } 1283 *miblen = offset; 1284 } 1285 1286 /** 1287 * ice_set_dcb_cfg - Set the local LLDP MIB to FW 1288 * @pi: port information structure 1289 * 1290 * Set DCB configuration to the Firmware 1291 */ 1292 enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi) 1293 { 1294 u8 mib_type, *lldpmib = NULL; 1295 struct ice_dcbx_cfg *dcbcfg; 1296 enum ice_status ret; 1297 struct ice_hw *hw; 1298 u16 miblen; 1299 1300 if (!pi) 1301 return ICE_ERR_PARAM; 1302 1303 hw = pi->hw; 1304 1305 /* update the HW local config */ 1306 dcbcfg = &pi->local_dcbx_cfg; 1307 /* Allocate the LLDPDU */ 1308 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL); 1309 if (!lldpmib) 1310 return ICE_ERR_NO_MEMORY; 1311 1312 mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB; 1313 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 1314 mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING; 1315 1316 ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg); 1317 ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, 1318 NULL); 1319 1320 devm_kfree(ice_hw_to_dev(hw), lldpmib); 1321 1322 return ret; 1323 } 1324 1325 /** 1326 * ice_aq_query_port_ets - query port ets configuration 1327 * @pi: port information structure 1328 * @buf: pointer to buffer 1329 * @buf_size: buffer size in bytes 1330 * @cd: pointer to command details structure or NULL 1331 * 1332 * query current port ets configuration 1333 */ 1334 static enum ice_status 1335 ice_aq_query_port_ets(struct ice_port_info *pi, 1336 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1337 struct ice_sq_cd *cd) 1338 { 1339 struct ice_aqc_query_port_ets *cmd; 1340 struct ice_aq_desc desc; 1341 enum ice_status status; 1342 1343 if (!pi) 1344 return ICE_ERR_PARAM; 1345 cmd = &desc.params.port_ets; 1346 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets); 1347 cmd->port_teid = pi->root->info.node_teid; 1348 1349 status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd); 1350 return status; 1351 } 1352 1353 /** 1354 * ice_update_port_tc_tree_cfg - update TC tree configuration 1355 * @pi: port information structure 1356 * @buf: pointer to buffer 1357 * 1358 * update the SW DB with the new TC changes 1359 */ 1360 static enum ice_status 1361 ice_update_port_tc_tree_cfg(struct ice_port_info *pi, 1362 struct ice_aqc_port_ets_elem *buf) 1363 { 1364 struct ice_sched_node *node, *tc_node; 1365 struct ice_aqc_get_elem elem; 1366 enum ice_status status = 0; 1367 u32 teid1, teid2; 1368 u8 i, j; 1369 1370 if (!pi) 1371 return ICE_ERR_PARAM; 1372 /* suspend the missing TC nodes */ 1373 for (i = 0; i < pi->root->num_children; i++) { 1374 teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid); 1375 ice_for_each_traffic_class(j) { 1376 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1377 if (teid1 == teid2) 1378 break; 1379 } 1380 if (j < ICE_MAX_TRAFFIC_CLASS) 1381 continue; 1382 /* TC is missing */ 1383 pi->root->children[i]->in_use = false; 1384 } 1385 /* add the new TC nodes */ 1386 ice_for_each_traffic_class(j) { 1387 teid2 = le32_to_cpu(buf->tc_node_teid[j]); 1388 if (teid2 == ICE_INVAL_TEID) 1389 continue; 1390 /* Is it already present in the tree ? */ 1391 for (i = 0; i < pi->root->num_children; i++) { 1392 tc_node = pi->root->children[i]; 1393 if (!tc_node) 1394 continue; 1395 teid1 = le32_to_cpu(tc_node->info.node_teid); 1396 if (teid1 == teid2) { 1397 tc_node->tc_num = j; 1398 tc_node->in_use = true; 1399 break; 1400 } 1401 } 1402 if (i < pi->root->num_children) 1403 continue; 1404 /* new TC */ 1405 status = ice_sched_query_elem(pi->hw, teid2, &elem); 1406 if (!status) 1407 status = ice_sched_add_node(pi, 1, &elem.generic[0]); 1408 if (status) 1409 break; 1410 /* update the TC number */ 1411 node = ice_sched_find_node_by_teid(pi->root, teid2); 1412 if (node) 1413 node->tc_num = j; 1414 } 1415 return status; 1416 } 1417 1418 /** 1419 * ice_query_port_ets - query port ets configuration 1420 * @pi: port information structure 1421 * @buf: pointer to buffer 1422 * @buf_size: buffer size in bytes 1423 * @cd: pointer to command details structure or NULL 1424 * 1425 * query current port ets configuration and update the 1426 * SW DB with the TC changes 1427 */ 1428 enum ice_status 1429 ice_query_port_ets(struct ice_port_info *pi, 1430 struct ice_aqc_port_ets_elem *buf, u16 buf_size, 1431 struct ice_sq_cd *cd) 1432 { 1433 enum ice_status status; 1434 1435 mutex_lock(&pi->sched_lock); 1436 status = ice_aq_query_port_ets(pi, buf, buf_size, cd); 1437 if (!status) 1438 status = ice_update_port_tc_tree_cfg(pi, buf); 1439 mutex_unlock(&pi->sched_lock); 1440 return status; 1441 } 1442