171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 371d10453SEric Joyner * All rights reserved. 471d10453SEric Joyner * 571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 671d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 771d10453SEric Joyner * 871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 971d10453SEric Joyner * this list of conditions and the following disclaimer. 1071d10453SEric Joyner * 1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 1371d10453SEric Joyner * documentation and/or other materials provided with the distribution. 1471d10453SEric Joyner * 1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from 1771d10453SEric Joyner * this software without specific prior written permission. 1871d10453SEric Joyner * 1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3071d10453SEric Joyner */ 3171d10453SEric Joyner 3271d10453SEric Joyner #include "ice_common.h" 3371d10453SEric Joyner #include "ice_sched.h" 3471d10453SEric Joyner #include "ice_dcb.h" 3571d10453SEric Joyner 3671d10453SEric Joyner /** 3771d10453SEric Joyner * ice_aq_get_lldp_mib 3871d10453SEric Joyner * @hw: pointer to the HW struct 3971d10453SEric Joyner * @bridge_type: type of bridge requested 4071d10453SEric Joyner * @mib_type: Local, Remote or both Local and Remote MIBs 4171d10453SEric Joyner * @buf: pointer to the caller-supplied buffer to store the MIB block 4271d10453SEric Joyner * @buf_size: size of the buffer (in bytes) 4371d10453SEric Joyner * @local_len: length of the returned Local LLDP MIB 4471d10453SEric Joyner * @remote_len: length of the returned Remote LLDP MIB 4571d10453SEric Joyner * @cd: pointer to command details structure or NULL 4671d10453SEric Joyner * 4771d10453SEric Joyner * Requests the complete LLDP MIB (entire packet). (0x0A00) 4871d10453SEric Joyner */ 49*f2635e84SEric Joyner int 5071d10453SEric Joyner ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf, 5171d10453SEric Joyner u16 buf_size, u16 *local_len, u16 *remote_len, 5271d10453SEric Joyner struct ice_sq_cd *cd) 5371d10453SEric Joyner { 5471d10453SEric Joyner struct ice_aqc_lldp_get_mib *cmd; 5571d10453SEric Joyner struct ice_aq_desc desc; 56*f2635e84SEric Joyner int status; 5771d10453SEric Joyner 5871d10453SEric Joyner cmd = &desc.params.lldp_get_mib; 5971d10453SEric Joyner 6071d10453SEric Joyner if (buf_size == 0 || !buf) 6171d10453SEric Joyner return ICE_ERR_PARAM; 6271d10453SEric Joyner 6371d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_get_mib); 6471d10453SEric Joyner 6571d10453SEric Joyner cmd->type = mib_type & ICE_AQ_LLDP_MIB_TYPE_M; 6671d10453SEric Joyner cmd->type |= (bridge_type << ICE_AQ_LLDP_BRID_TYPE_S) & 6771d10453SEric Joyner ICE_AQ_LLDP_BRID_TYPE_M; 6871d10453SEric Joyner 6971d10453SEric Joyner desc.datalen = CPU_TO_LE16(buf_size); 7071d10453SEric Joyner 7171d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 7271d10453SEric Joyner if (!status) { 7371d10453SEric Joyner if (local_len) 7471d10453SEric Joyner *local_len = LE16_TO_CPU(cmd->local_len); 7571d10453SEric Joyner if (remote_len) 7671d10453SEric Joyner *remote_len = LE16_TO_CPU(cmd->remote_len); 7771d10453SEric Joyner } 7871d10453SEric Joyner 7971d10453SEric Joyner return status; 8071d10453SEric Joyner } 8171d10453SEric Joyner 8271d10453SEric Joyner /** 8371d10453SEric Joyner * ice_aq_cfg_lldp_mib_change 8471d10453SEric Joyner * @hw: pointer to the HW struct 8571d10453SEric Joyner * @ena_update: Enable or Disable event posting 8671d10453SEric Joyner * @cd: pointer to command details structure or NULL 8771d10453SEric Joyner * 8871d10453SEric Joyner * Enable or Disable posting of an event on ARQ when LLDP MIB 8971d10453SEric Joyner * associated with the interface changes (0x0A01) 9071d10453SEric Joyner */ 91*f2635e84SEric Joyner int 9271d10453SEric Joyner ice_aq_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_update, 9371d10453SEric Joyner struct ice_sq_cd *cd) 9471d10453SEric Joyner { 9571d10453SEric Joyner struct ice_aqc_lldp_set_mib_change *cmd; 9671d10453SEric Joyner struct ice_aq_desc desc; 9771d10453SEric Joyner 9871d10453SEric Joyner cmd = &desc.params.lldp_set_event; 9971d10453SEric Joyner 10071d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_mib_change); 10171d10453SEric Joyner 10271d10453SEric Joyner if (!ena_update) 10371d10453SEric Joyner cmd->command |= ICE_AQ_LLDP_MIB_UPDATE_DIS; 1048923de59SPiotr Kubaj else 1058923de59SPiotr Kubaj cmd->command |= ICE_AQ_LLDP_MIB_PENDING_ENABLE << 1068923de59SPiotr Kubaj ICE_AQ_LLDP_MIB_PENDING_S; 10771d10453SEric Joyner 10871d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 10971d10453SEric Joyner } 11071d10453SEric Joyner 11171d10453SEric Joyner /** 11271d10453SEric Joyner * ice_aq_add_delete_lldp_tlv 11371d10453SEric Joyner * @hw: pointer to the HW struct 11471d10453SEric Joyner * @bridge_type: type of bridge 11571d10453SEric Joyner * @add_lldp_tlv: add (true) or delete (false) TLV 11671d10453SEric Joyner * @buf: buffer with TLV to add or delete 11771d10453SEric Joyner * @buf_size: length of the buffer 11871d10453SEric Joyner * @tlv_len: length of the TLV to be added/deleted 11971d10453SEric Joyner * @mib_len: length of the LLDP MIB returned in response 12071d10453SEric Joyner * @cd: pointer to command details structure or NULL 12171d10453SEric Joyner * 12271d10453SEric Joyner * (Add tlv) 12371d10453SEric Joyner * Add the specified TLV to LLDP Local MIB for the given bridge type, 12471d10453SEric Joyner * it is responsibility of the caller to make sure that the TLV is not 12571d10453SEric Joyner * already present in the LLDPDU. 12671d10453SEric Joyner * In return firmware will write the complete LLDP MIB with the newly 12771d10453SEric Joyner * added TLV in the response buffer. (0x0A02) 12871d10453SEric Joyner * 12971d10453SEric Joyner * (Delete tlv) 13071d10453SEric Joyner * Delete the specified TLV from LLDP Local MIB for the given bridge type. 13171d10453SEric Joyner * The firmware places the entire LLDP MIB in the response buffer. (0x0A04) 13271d10453SEric Joyner */ 133*f2635e84SEric Joyner int 13471d10453SEric Joyner ice_aq_add_delete_lldp_tlv(struct ice_hw *hw, u8 bridge_type, bool add_lldp_tlv, 13571d10453SEric Joyner void *buf, u16 buf_size, u16 tlv_len, u16 *mib_len, 13671d10453SEric Joyner struct ice_sq_cd *cd) 13771d10453SEric Joyner { 13871d10453SEric Joyner struct ice_aqc_lldp_add_delete_tlv *cmd; 13971d10453SEric Joyner struct ice_aq_desc desc; 140*f2635e84SEric Joyner int status; 14171d10453SEric Joyner 14271d10453SEric Joyner if (tlv_len == 0) 14371d10453SEric Joyner return ICE_ERR_PARAM; 14471d10453SEric Joyner 14571d10453SEric Joyner cmd = &desc.params.lldp_add_delete_tlv; 14671d10453SEric Joyner 14771d10453SEric Joyner if (add_lldp_tlv) 14871d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_add_tlv); 14971d10453SEric Joyner else 15071d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, 15171d10453SEric Joyner ice_aqc_opc_lldp_delete_tlv); 15271d10453SEric Joyner 15371d10453SEric Joyner desc.flags |= CPU_TO_LE16((u16)(ICE_AQ_FLAG_RD)); 15471d10453SEric Joyner 15571d10453SEric Joyner cmd->type = ((bridge_type << ICE_AQ_LLDP_BRID_TYPE_S) & 15671d10453SEric Joyner ICE_AQ_LLDP_BRID_TYPE_M); 15771d10453SEric Joyner cmd->len = CPU_TO_LE16(tlv_len); 15871d10453SEric Joyner 15971d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 16071d10453SEric Joyner if (!status && mib_len) 16171d10453SEric Joyner *mib_len = LE16_TO_CPU(desc.datalen); 16271d10453SEric Joyner 16371d10453SEric Joyner return status; 16471d10453SEric Joyner } 16571d10453SEric Joyner 16671d10453SEric Joyner /** 16771d10453SEric Joyner * ice_aq_update_lldp_tlv 16871d10453SEric Joyner * @hw: pointer to the HW struct 16971d10453SEric Joyner * @bridge_type: type of bridge 17071d10453SEric Joyner * @buf: buffer with TLV to update 17171d10453SEric Joyner * @buf_size: size of the buffer holding original and updated TLVs 17271d10453SEric Joyner * @old_len: Length of the Original TLV 17371d10453SEric Joyner * @new_len: Length of the Updated TLV 17471d10453SEric Joyner * @offset: offset of the updated TLV in the buff 17571d10453SEric Joyner * @mib_len: length of the returned LLDP MIB 17671d10453SEric Joyner * @cd: pointer to command details structure or NULL 17771d10453SEric Joyner * 17871d10453SEric Joyner * Update the specified TLV to the LLDP Local MIB for the given bridge type. 17971d10453SEric Joyner * Firmware will place the complete LLDP MIB in response buffer with the 18071d10453SEric Joyner * updated TLV. (0x0A03) 18171d10453SEric Joyner */ 182*f2635e84SEric Joyner int 18371d10453SEric Joyner ice_aq_update_lldp_tlv(struct ice_hw *hw, u8 bridge_type, void *buf, 18471d10453SEric Joyner u16 buf_size, u16 old_len, u16 new_len, u16 offset, 18571d10453SEric Joyner u16 *mib_len, struct ice_sq_cd *cd) 18671d10453SEric Joyner { 18771d10453SEric Joyner struct ice_aqc_lldp_update_tlv *cmd; 18871d10453SEric Joyner struct ice_aq_desc desc; 189*f2635e84SEric Joyner int status; 19071d10453SEric Joyner 19171d10453SEric Joyner cmd = &desc.params.lldp_update_tlv; 19271d10453SEric Joyner 19371d10453SEric Joyner if (offset == 0 || old_len == 0 || new_len == 0) 19471d10453SEric Joyner return ICE_ERR_PARAM; 19571d10453SEric Joyner 19671d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_update_tlv); 19771d10453SEric Joyner 19871d10453SEric Joyner desc.flags |= CPU_TO_LE16((u16)(ICE_AQ_FLAG_RD)); 19971d10453SEric Joyner 20071d10453SEric Joyner cmd->type = ((bridge_type << ICE_AQ_LLDP_BRID_TYPE_S) & 20171d10453SEric Joyner ICE_AQ_LLDP_BRID_TYPE_M); 20271d10453SEric Joyner cmd->old_len = CPU_TO_LE16(old_len); 20371d10453SEric Joyner cmd->new_offset = CPU_TO_LE16(offset); 20471d10453SEric Joyner cmd->new_len = CPU_TO_LE16(new_len); 20571d10453SEric Joyner 20671d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 20771d10453SEric Joyner if (!status && mib_len) 20871d10453SEric Joyner *mib_len = LE16_TO_CPU(desc.datalen); 20971d10453SEric Joyner 21071d10453SEric Joyner return status; 21171d10453SEric Joyner } 21271d10453SEric Joyner 21371d10453SEric Joyner /** 21471d10453SEric Joyner * ice_aq_stop_lldp 21571d10453SEric Joyner * @hw: pointer to the HW struct 21671d10453SEric Joyner * @shutdown_lldp_agent: True if LLDP Agent needs to be Shutdown 21771d10453SEric Joyner * False if LLDP Agent needs to be Stopped 21871d10453SEric Joyner * @persist: True if Stop/Shutdown of LLDP Agent needs to be persistent across 21971d10453SEric Joyner * reboots 22071d10453SEric Joyner * @cd: pointer to command details structure or NULL 22171d10453SEric Joyner * 22271d10453SEric Joyner * Stop or Shutdown the embedded LLDP Agent (0x0A05) 22371d10453SEric Joyner */ 224*f2635e84SEric Joyner int 22571d10453SEric Joyner ice_aq_stop_lldp(struct ice_hw *hw, bool shutdown_lldp_agent, bool persist, 22671d10453SEric Joyner struct ice_sq_cd *cd) 22771d10453SEric Joyner { 22871d10453SEric Joyner struct ice_aqc_lldp_stop *cmd; 22971d10453SEric Joyner struct ice_aq_desc desc; 23071d10453SEric Joyner 23171d10453SEric Joyner cmd = &desc.params.lldp_stop; 23271d10453SEric Joyner 23371d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_stop); 23471d10453SEric Joyner 23571d10453SEric Joyner if (shutdown_lldp_agent) 23671d10453SEric Joyner cmd->command |= ICE_AQ_LLDP_AGENT_SHUTDOWN; 23771d10453SEric Joyner 23871d10453SEric Joyner if (persist) 23971d10453SEric Joyner cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_DIS; 24071d10453SEric Joyner 24171d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 24271d10453SEric Joyner } 24371d10453SEric Joyner 24471d10453SEric Joyner /** 24571d10453SEric Joyner * ice_aq_start_lldp 24671d10453SEric Joyner * @hw: pointer to the HW struct 24771d10453SEric Joyner * @persist: True if Start of LLDP Agent needs to be persistent across reboots 24871d10453SEric Joyner * @cd: pointer to command details structure or NULL 24971d10453SEric Joyner * 25071d10453SEric Joyner * Start the embedded LLDP Agent on all ports. (0x0A06) 25171d10453SEric Joyner */ 252*f2635e84SEric Joyner int 25371d10453SEric Joyner ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd) 25471d10453SEric Joyner { 25571d10453SEric Joyner struct ice_aqc_lldp_start *cmd; 25671d10453SEric Joyner struct ice_aq_desc desc; 25771d10453SEric Joyner 25871d10453SEric Joyner cmd = &desc.params.lldp_start; 25971d10453SEric Joyner 26071d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start); 26171d10453SEric Joyner 26271d10453SEric Joyner cmd->command = ICE_AQ_LLDP_AGENT_START; 26371d10453SEric Joyner 26471d10453SEric Joyner if (persist) 26571d10453SEric Joyner cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_ENA; 26671d10453SEric Joyner 26771d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 26871d10453SEric Joyner } 26971d10453SEric Joyner 27071d10453SEric Joyner /** 27171d10453SEric Joyner * ice_get_dcbx_status 27271d10453SEric Joyner * @hw: pointer to the HW struct 27371d10453SEric Joyner * 27471d10453SEric Joyner * Get the DCBX status from the Firmware 27571d10453SEric Joyner */ 27671d10453SEric Joyner u8 ice_get_dcbx_status(struct ice_hw *hw) 27771d10453SEric Joyner { 27871d10453SEric Joyner u32 reg; 27971d10453SEric Joyner 28071d10453SEric Joyner reg = rd32(hw, PRTDCB_GENS); 28171d10453SEric Joyner return (u8)((reg & PRTDCB_GENS_DCBX_STATUS_M) >> 28271d10453SEric Joyner PRTDCB_GENS_DCBX_STATUS_S); 28371d10453SEric Joyner } 28471d10453SEric Joyner 28571d10453SEric Joyner /** 28671d10453SEric Joyner * ice_parse_ieee_ets_common_tlv 28771d10453SEric Joyner * @buf: Data buffer to be parsed for ETS CFG/REC data 28871d10453SEric Joyner * @ets_cfg: Container to store parsed data 28971d10453SEric Joyner * 29071d10453SEric Joyner * Parses the common data of IEEE 802.1Qaz ETS CFG/REC TLV 29171d10453SEric Joyner */ 29271d10453SEric Joyner static void 29371d10453SEric Joyner ice_parse_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 29471d10453SEric Joyner { 29571d10453SEric Joyner u8 offset = 0; 29671d10453SEric Joyner int i; 29771d10453SEric Joyner 29871d10453SEric Joyner /* Priority Assignment Table (4 octets) 29971d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 30071d10453SEric Joyner * ----------------------------------------- 30171d10453SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 30271d10453SEric Joyner * ----------------------------------------- 30371d10453SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 30471d10453SEric Joyner * ----------------------------------------- 30571d10453SEric Joyner */ 30671d10453SEric Joyner for (i = 0; i < 4; i++) { 30771d10453SEric Joyner ets_cfg->prio_table[i * 2] = 30871d10453SEric Joyner ((buf[offset] & ICE_IEEE_ETS_PRIO_1_M) >> 30971d10453SEric Joyner ICE_IEEE_ETS_PRIO_1_S); 31071d10453SEric Joyner ets_cfg->prio_table[i * 2 + 1] = 31171d10453SEric Joyner ((buf[offset] & ICE_IEEE_ETS_PRIO_0_M) >> 31271d10453SEric Joyner ICE_IEEE_ETS_PRIO_0_S); 31371d10453SEric Joyner offset++; 31471d10453SEric Joyner } 31571d10453SEric Joyner 31671d10453SEric Joyner /* TC Bandwidth Table (8 octets) 31771d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 31871d10453SEric Joyner * --------------------------------- 31971d10453SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 32071d10453SEric Joyner * --------------------------------- 32171d10453SEric Joyner * 32271d10453SEric Joyner * TSA Assignment Table (8 octets) 32371d10453SEric Joyner * Octets:| 9 | 10| 11| 12| 13| 14| 15| 16| 32471d10453SEric Joyner * --------------------------------- 32571d10453SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 32671d10453SEric Joyner * --------------------------------- 32771d10453SEric Joyner */ 32871d10453SEric Joyner ice_for_each_traffic_class(i) { 32971d10453SEric Joyner ets_cfg->tcbwtable[i] = buf[offset]; 33071d10453SEric Joyner ets_cfg->tsatable[i] = buf[ICE_MAX_TRAFFIC_CLASS + offset++]; 33171d10453SEric Joyner } 33271d10453SEric Joyner } 33371d10453SEric Joyner 33471d10453SEric Joyner /** 33571d10453SEric Joyner * ice_parse_ieee_etscfg_tlv 33671d10453SEric Joyner * @tlv: IEEE 802.1Qaz ETS CFG TLV 33771d10453SEric Joyner * @dcbcfg: Local store to update ETS CFG data 33871d10453SEric Joyner * 33971d10453SEric Joyner * Parses IEEE 802.1Qaz ETS CFG TLV 34071d10453SEric Joyner */ 34171d10453SEric Joyner static void 34271d10453SEric Joyner ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv *tlv, 34371d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 34471d10453SEric Joyner { 34571d10453SEric Joyner struct ice_dcb_ets_cfg *etscfg; 34671d10453SEric Joyner u8 *buf = tlv->tlvinfo; 34771d10453SEric Joyner 34871d10453SEric Joyner /* First Octet post subtype 34971d10453SEric Joyner * -------------------------- 35071d10453SEric Joyner * |will-|CBS | Re- | Max | 35171d10453SEric Joyner * |ing | |served| TCs | 35271d10453SEric Joyner * -------------------------- 35371d10453SEric Joyner * |1bit | 1bit|3 bits|3bits| 35471d10453SEric Joyner */ 35571d10453SEric Joyner etscfg = &dcbcfg->etscfg; 35671d10453SEric Joyner etscfg->willing = ((buf[0] & ICE_IEEE_ETS_WILLING_M) >> 35771d10453SEric Joyner ICE_IEEE_ETS_WILLING_S); 35871d10453SEric Joyner etscfg->cbs = ((buf[0] & ICE_IEEE_ETS_CBS_M) >> ICE_IEEE_ETS_CBS_S); 35971d10453SEric Joyner etscfg->maxtcs = ((buf[0] & ICE_IEEE_ETS_MAXTC_M) >> 36071d10453SEric Joyner ICE_IEEE_ETS_MAXTC_S); 36171d10453SEric Joyner 36271d10453SEric Joyner /* Begin parsing at Priority Assignment Table (offset 1 in buf) */ 36371d10453SEric Joyner ice_parse_ieee_ets_common_tlv(&buf[1], etscfg); 36471d10453SEric Joyner } 36571d10453SEric Joyner 36671d10453SEric Joyner /** 36771d10453SEric Joyner * ice_parse_ieee_etsrec_tlv 36871d10453SEric Joyner * @tlv: IEEE 802.1Qaz ETS REC TLV 36971d10453SEric Joyner * @dcbcfg: Local store to update ETS REC data 37071d10453SEric Joyner * 37171d10453SEric Joyner * Parses IEEE 802.1Qaz ETS REC TLV 37271d10453SEric Joyner */ 37371d10453SEric Joyner static void 37471d10453SEric Joyner ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 37571d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 37671d10453SEric Joyner { 37771d10453SEric Joyner u8 *buf = tlv->tlvinfo; 37871d10453SEric Joyner 37971d10453SEric Joyner /* Begin parsing at Priority Assignment Table (offset 1 in buf) */ 38071d10453SEric Joyner ice_parse_ieee_ets_common_tlv(&buf[1], &dcbcfg->etsrec); 38171d10453SEric Joyner } 38271d10453SEric Joyner 38371d10453SEric Joyner /** 38471d10453SEric Joyner * ice_parse_ieee_pfccfg_tlv 38571d10453SEric Joyner * @tlv: IEEE 802.1Qaz PFC CFG TLV 38671d10453SEric Joyner * @dcbcfg: Local store to update PFC CFG data 38771d10453SEric Joyner * 38871d10453SEric Joyner * Parses IEEE 802.1Qaz PFC CFG TLV 38971d10453SEric Joyner */ 39071d10453SEric Joyner static void 39171d10453SEric Joyner ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv *tlv, 39271d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 39371d10453SEric Joyner { 39471d10453SEric Joyner u8 *buf = tlv->tlvinfo; 39571d10453SEric Joyner 39671d10453SEric Joyner /* ---------------------------------------- 39771d10453SEric Joyner * |will-|MBC | Re- | PFC | PFC Enable | 39871d10453SEric Joyner * |ing | |served| cap | | 39971d10453SEric Joyner * ----------------------------------------- 40071d10453SEric Joyner * |1bit | 1bit|2 bits|4bits| 1 octet | 40171d10453SEric Joyner */ 40271d10453SEric Joyner dcbcfg->pfc.willing = ((buf[0] & ICE_IEEE_PFC_WILLING_M) >> 40371d10453SEric Joyner ICE_IEEE_PFC_WILLING_S); 40471d10453SEric Joyner dcbcfg->pfc.mbc = ((buf[0] & ICE_IEEE_PFC_MBC_M) >> ICE_IEEE_PFC_MBC_S); 40571d10453SEric Joyner dcbcfg->pfc.pfccap = ((buf[0] & ICE_IEEE_PFC_CAP_M) >> 40671d10453SEric Joyner ICE_IEEE_PFC_CAP_S); 40771d10453SEric Joyner dcbcfg->pfc.pfcena = buf[1]; 40871d10453SEric Joyner } 40971d10453SEric Joyner 41071d10453SEric Joyner /** 41171d10453SEric Joyner * ice_parse_ieee_app_tlv 41271d10453SEric Joyner * @tlv: IEEE 802.1Qaz APP TLV 41371d10453SEric Joyner * @dcbcfg: Local store to update APP PRIO data 41471d10453SEric Joyner * 41571d10453SEric Joyner * Parses IEEE 802.1Qaz APP PRIO TLV 41671d10453SEric Joyner */ 41771d10453SEric Joyner static void 41871d10453SEric Joyner ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv *tlv, 41971d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 42071d10453SEric Joyner { 42171d10453SEric Joyner u16 offset = 0; 42271d10453SEric Joyner u16 typelen; 42371d10453SEric Joyner int i = 0; 42471d10453SEric Joyner u16 len; 42571d10453SEric Joyner u8 *buf; 42671d10453SEric Joyner 42771d10453SEric Joyner typelen = NTOHS(tlv->typelen); 42871d10453SEric Joyner len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 42971d10453SEric Joyner buf = tlv->tlvinfo; 43071d10453SEric Joyner 43171d10453SEric Joyner /* Removing sizeof(ouisubtype) and reserved byte from len. 43271d10453SEric Joyner * Remaining len div 3 is number of APP TLVs. 43371d10453SEric Joyner */ 43471d10453SEric Joyner len -= (sizeof(tlv->ouisubtype) + 1); 43571d10453SEric Joyner 43671d10453SEric Joyner /* Move offset to App Priority Table */ 43771d10453SEric Joyner offset++; 43871d10453SEric Joyner 43971d10453SEric Joyner /* Application Priority Table (3 octets) 44071d10453SEric Joyner * Octets:| 1 | 2 | 3 | 44171d10453SEric Joyner * ----------------------------------------- 44271d10453SEric Joyner * |Priority|Rsrvd| Sel | Protocol ID | 44371d10453SEric Joyner * ----------------------------------------- 44471d10453SEric Joyner * Bits:|23 21|20 19|18 16|15 0| 44571d10453SEric Joyner * ----------------------------------------- 44671d10453SEric Joyner */ 44771d10453SEric Joyner while (offset < len) { 44871d10453SEric Joyner dcbcfg->app[i].priority = ((buf[offset] & 44971d10453SEric Joyner ICE_IEEE_APP_PRIO_M) >> 45071d10453SEric Joyner ICE_IEEE_APP_PRIO_S); 45171d10453SEric Joyner dcbcfg->app[i].selector = ((buf[offset] & 45271d10453SEric Joyner ICE_IEEE_APP_SEL_M) >> 45371d10453SEric Joyner ICE_IEEE_APP_SEL_S); 45471d10453SEric Joyner dcbcfg->app[i].prot_id = (buf[offset + 1] << 0x8) | 45571d10453SEric Joyner buf[offset + 2]; 45671d10453SEric Joyner /* Move to next app */ 45771d10453SEric Joyner offset += 3; 45871d10453SEric Joyner i++; 45971d10453SEric Joyner if (i >= ICE_DCBX_MAX_APPS) 46071d10453SEric Joyner break; 46171d10453SEric Joyner } 46271d10453SEric Joyner 46371d10453SEric Joyner dcbcfg->numapps = i; 46471d10453SEric Joyner } 46571d10453SEric Joyner 46671d10453SEric Joyner /** 46771d10453SEric Joyner * ice_parse_ieee_tlv 46871d10453SEric Joyner * @tlv: IEEE 802.1Qaz TLV 46971d10453SEric Joyner * @dcbcfg: Local store to update ETS REC data 47071d10453SEric Joyner * 47171d10453SEric Joyner * Get the TLV subtype and send it to parsing function 47271d10453SEric Joyner * based on the subtype value 47371d10453SEric Joyner */ 47471d10453SEric Joyner static void 47571d10453SEric Joyner ice_parse_ieee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 47671d10453SEric Joyner { 47771d10453SEric Joyner u32 ouisubtype; 47871d10453SEric Joyner u8 subtype; 47971d10453SEric Joyner 48071d10453SEric Joyner ouisubtype = NTOHL(tlv->ouisubtype); 48171d10453SEric Joyner subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >> 48271d10453SEric Joyner ICE_LLDP_TLV_SUBTYPE_S); 48371d10453SEric Joyner switch (subtype) { 48471d10453SEric Joyner case ICE_IEEE_SUBTYPE_ETS_CFG: 48571d10453SEric Joyner ice_parse_ieee_etscfg_tlv(tlv, dcbcfg); 48671d10453SEric Joyner break; 48771d10453SEric Joyner case ICE_IEEE_SUBTYPE_ETS_REC: 48871d10453SEric Joyner ice_parse_ieee_etsrec_tlv(tlv, dcbcfg); 48971d10453SEric Joyner break; 49071d10453SEric Joyner case ICE_IEEE_SUBTYPE_PFC_CFG: 49171d10453SEric Joyner ice_parse_ieee_pfccfg_tlv(tlv, dcbcfg); 49271d10453SEric Joyner break; 49371d10453SEric Joyner case ICE_IEEE_SUBTYPE_APP_PRI: 49471d10453SEric Joyner ice_parse_ieee_app_tlv(tlv, dcbcfg); 49571d10453SEric Joyner break; 49671d10453SEric Joyner default: 49771d10453SEric Joyner break; 49871d10453SEric Joyner } 49971d10453SEric Joyner } 50071d10453SEric Joyner 50171d10453SEric Joyner /** 50271d10453SEric Joyner * ice_parse_cee_pgcfg_tlv 50371d10453SEric Joyner * @tlv: CEE DCBX PG CFG TLV 50471d10453SEric Joyner * @dcbcfg: Local store to update ETS CFG data 50571d10453SEric Joyner * 50671d10453SEric Joyner * Parses CEE DCBX PG CFG TLV 50771d10453SEric Joyner */ 50871d10453SEric Joyner static void 50971d10453SEric Joyner ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv *tlv, 51071d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 51171d10453SEric Joyner { 51271d10453SEric Joyner struct ice_dcb_ets_cfg *etscfg; 51371d10453SEric Joyner u8 *buf = tlv->tlvinfo; 51471d10453SEric Joyner u16 offset = 0; 51571d10453SEric Joyner int i; 51671d10453SEric Joyner 51771d10453SEric Joyner etscfg = &dcbcfg->etscfg; 51871d10453SEric Joyner 51971d10453SEric Joyner if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M) 52071d10453SEric Joyner etscfg->willing = 1; 52171d10453SEric Joyner 52271d10453SEric Joyner etscfg->cbs = 0; 52371d10453SEric Joyner /* Priority Group Table (4 octets) 52471d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 52571d10453SEric Joyner * ----------------------------------------- 52671d10453SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 52771d10453SEric Joyner * ----------------------------------------- 52871d10453SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 52971d10453SEric Joyner * ----------------------------------------- 53071d10453SEric Joyner */ 53171d10453SEric Joyner for (i = 0; i < 4; i++) { 53271d10453SEric Joyner etscfg->prio_table[i * 2] = 53371d10453SEric Joyner ((buf[offset] & ICE_CEE_PGID_PRIO_1_M) >> 53471d10453SEric Joyner ICE_CEE_PGID_PRIO_1_S); 53571d10453SEric Joyner etscfg->prio_table[i * 2 + 1] = 53671d10453SEric Joyner ((buf[offset] & ICE_CEE_PGID_PRIO_0_M) >> 53771d10453SEric Joyner ICE_CEE_PGID_PRIO_0_S); 53871d10453SEric Joyner offset++; 53971d10453SEric Joyner } 54071d10453SEric Joyner 54171d10453SEric Joyner /* PG Percentage Table (8 octets) 54271d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 54371d10453SEric Joyner * --------------------------------- 54471d10453SEric Joyner * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7| 54571d10453SEric Joyner * --------------------------------- 54671d10453SEric Joyner */ 54771d10453SEric Joyner ice_for_each_traffic_class(i) { 54871d10453SEric Joyner etscfg->tcbwtable[i] = buf[offset++]; 54971d10453SEric Joyner 55071d10453SEric Joyner if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT) 55171d10453SEric Joyner dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 55271d10453SEric Joyner else 55371d10453SEric Joyner dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 55471d10453SEric Joyner } 55571d10453SEric Joyner 55671d10453SEric Joyner /* Number of TCs supported (1 octet) */ 55771d10453SEric Joyner etscfg->maxtcs = buf[offset]; 55871d10453SEric Joyner } 55971d10453SEric Joyner 56071d10453SEric Joyner /** 56171d10453SEric Joyner * ice_parse_cee_pfccfg_tlv 56271d10453SEric Joyner * @tlv: CEE DCBX PFC CFG TLV 56371d10453SEric Joyner * @dcbcfg: Local store to update PFC CFG data 56471d10453SEric Joyner * 56571d10453SEric Joyner * Parses CEE DCBX PFC CFG TLV 56671d10453SEric Joyner */ 56771d10453SEric Joyner static void 56871d10453SEric Joyner ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv, 56971d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 57071d10453SEric Joyner { 57171d10453SEric Joyner u8 *buf = tlv->tlvinfo; 57271d10453SEric Joyner 57371d10453SEric Joyner if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M) 57471d10453SEric Joyner dcbcfg->pfc.willing = 1; 57571d10453SEric Joyner 57671d10453SEric Joyner /* ------------------------ 57771d10453SEric Joyner * | PFC Enable | PFC TCs | 57871d10453SEric Joyner * ------------------------ 57971d10453SEric Joyner * | 1 octet | 1 octet | 58071d10453SEric Joyner */ 58171d10453SEric Joyner dcbcfg->pfc.pfcena = buf[0]; 58271d10453SEric Joyner dcbcfg->pfc.pfccap = buf[1]; 58371d10453SEric Joyner } 58471d10453SEric Joyner 58571d10453SEric Joyner /** 58671d10453SEric Joyner * ice_parse_cee_app_tlv 58771d10453SEric Joyner * @tlv: CEE DCBX APP TLV 58871d10453SEric Joyner * @dcbcfg: Local store to update APP PRIO data 58971d10453SEric Joyner * 59071d10453SEric Joyner * Parses CEE DCBX APP PRIO TLV 59171d10453SEric Joyner */ 59271d10453SEric Joyner static void 59371d10453SEric Joyner ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 59471d10453SEric Joyner { 59571d10453SEric Joyner u16 len, typelen, offset = 0; 59671d10453SEric Joyner struct ice_cee_app_prio *app; 59771d10453SEric Joyner u8 i; 59871d10453SEric Joyner 59971d10453SEric Joyner typelen = NTOHS(tlv->hdr.typelen); 60071d10453SEric Joyner len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 60171d10453SEric Joyner 60271d10453SEric Joyner dcbcfg->numapps = len / sizeof(*app); 60371d10453SEric Joyner if (!dcbcfg->numapps) 60471d10453SEric Joyner return; 60571d10453SEric Joyner if (dcbcfg->numapps > ICE_DCBX_MAX_APPS) 60671d10453SEric Joyner dcbcfg->numapps = ICE_DCBX_MAX_APPS; 60771d10453SEric Joyner 60871d10453SEric Joyner for (i = 0; i < dcbcfg->numapps; i++) { 60971d10453SEric Joyner u8 up, selector; 61071d10453SEric Joyner 61171d10453SEric Joyner app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset); 61271d10453SEric Joyner for (up = 0; up < ICE_MAX_USER_PRIORITY; up++) 61371d10453SEric Joyner if (app->prio_map & BIT(up)) 61471d10453SEric Joyner break; 61571d10453SEric Joyner 61671d10453SEric Joyner dcbcfg->app[i].priority = up; 61771d10453SEric Joyner 61871d10453SEric Joyner /* Get Selector from lower 2 bits, and convert to IEEE */ 61971d10453SEric Joyner selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M); 62071d10453SEric Joyner switch (selector) { 62171d10453SEric Joyner case ICE_CEE_APP_SEL_ETHTYPE: 62271d10453SEric Joyner dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE; 62371d10453SEric Joyner break; 62471d10453SEric Joyner case ICE_CEE_APP_SEL_TCPIP: 62571d10453SEric Joyner dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP; 62671d10453SEric Joyner break; 62771d10453SEric Joyner default: 62871d10453SEric Joyner /* Keep selector as it is for unknown types */ 62971d10453SEric Joyner dcbcfg->app[i].selector = selector; 63071d10453SEric Joyner } 63171d10453SEric Joyner 63271d10453SEric Joyner dcbcfg->app[i].prot_id = NTOHS(app->protocol); 63371d10453SEric Joyner /* Move to next app */ 63471d10453SEric Joyner offset += sizeof(*app); 63571d10453SEric Joyner } 63671d10453SEric Joyner } 63771d10453SEric Joyner 63871d10453SEric Joyner /** 63971d10453SEric Joyner * ice_parse_cee_tlv 64071d10453SEric Joyner * @tlv: CEE DCBX TLV 64171d10453SEric Joyner * @dcbcfg: Local store to update DCBX config data 64271d10453SEric Joyner * 64371d10453SEric Joyner * Get the TLV subtype and send it to parsing function 64471d10453SEric Joyner * based on the subtype value 64571d10453SEric Joyner */ 64671d10453SEric Joyner static void 64771d10453SEric Joyner ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 64871d10453SEric Joyner { 64971d10453SEric Joyner struct ice_cee_feat_tlv *sub_tlv; 65071d10453SEric Joyner u8 subtype, feat_tlv_count = 0; 65171d10453SEric Joyner u16 len, tlvlen, typelen; 65271d10453SEric Joyner u32 ouisubtype; 65371d10453SEric Joyner 65471d10453SEric Joyner ouisubtype = NTOHL(tlv->ouisubtype); 65571d10453SEric Joyner subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >> 65671d10453SEric Joyner ICE_LLDP_TLV_SUBTYPE_S); 65771d10453SEric Joyner /* Return if not CEE DCBX */ 65871d10453SEric Joyner if (subtype != ICE_CEE_DCBX_TYPE) 65971d10453SEric Joyner return; 66071d10453SEric Joyner 66171d10453SEric Joyner typelen = NTOHS(tlv->typelen); 66271d10453SEric Joyner tlvlen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 66371d10453SEric Joyner len = sizeof(tlv->typelen) + sizeof(ouisubtype) + 66471d10453SEric Joyner sizeof(struct ice_cee_ctrl_tlv); 66571d10453SEric Joyner /* Return if no CEE DCBX Feature TLVs */ 66671d10453SEric Joyner if (tlvlen <= len) 66771d10453SEric Joyner return; 66871d10453SEric Joyner 66971d10453SEric Joyner sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len); 67071d10453SEric Joyner while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) { 67171d10453SEric Joyner u16 sublen; 67271d10453SEric Joyner 67371d10453SEric Joyner typelen = NTOHS(sub_tlv->hdr.typelen); 67471d10453SEric Joyner sublen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 67571d10453SEric Joyner subtype = (u8)((typelen & ICE_LLDP_TLV_TYPE_M) >> 67671d10453SEric Joyner ICE_LLDP_TLV_TYPE_S); 67771d10453SEric Joyner switch (subtype) { 67871d10453SEric Joyner case ICE_CEE_SUBTYPE_PG_CFG: 67971d10453SEric Joyner ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); 68071d10453SEric Joyner break; 68171d10453SEric Joyner case ICE_CEE_SUBTYPE_PFC_CFG: 68271d10453SEric Joyner ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); 68371d10453SEric Joyner break; 68471d10453SEric Joyner case ICE_CEE_SUBTYPE_APP_PRI: 68571d10453SEric Joyner ice_parse_cee_app_tlv(sub_tlv, dcbcfg); 68671d10453SEric Joyner break; 68771d10453SEric Joyner default: 68871d10453SEric Joyner return; /* Invalid Sub-type return */ 68971d10453SEric Joyner } 69071d10453SEric Joyner feat_tlv_count++; 69171d10453SEric Joyner /* Move to next sub TLV */ 69271d10453SEric Joyner sub_tlv = (struct ice_cee_feat_tlv *) 69371d10453SEric Joyner ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) + 69471d10453SEric Joyner sublen); 69571d10453SEric Joyner } 69671d10453SEric Joyner } 69771d10453SEric Joyner 69871d10453SEric Joyner /** 69971d10453SEric Joyner * ice_parse_org_tlv 70071d10453SEric Joyner * @tlv: Organization specific TLV 70171d10453SEric Joyner * @dcbcfg: Local store to update ETS REC data 70271d10453SEric Joyner * 70371d10453SEric Joyner * Currently only IEEE 802.1Qaz TLV is supported, all others 70471d10453SEric Joyner * will be returned 70571d10453SEric Joyner */ 70671d10453SEric Joyner static void 70771d10453SEric Joyner ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 70871d10453SEric Joyner { 70971d10453SEric Joyner u32 ouisubtype; 71071d10453SEric Joyner u32 oui; 71171d10453SEric Joyner 71271d10453SEric Joyner ouisubtype = NTOHL(tlv->ouisubtype); 71371d10453SEric Joyner oui = ((ouisubtype & ICE_LLDP_TLV_OUI_M) >> ICE_LLDP_TLV_OUI_S); 71471d10453SEric Joyner switch (oui) { 71571d10453SEric Joyner case ICE_IEEE_8021QAZ_OUI: 71671d10453SEric Joyner ice_parse_ieee_tlv(tlv, dcbcfg); 71771d10453SEric Joyner break; 71871d10453SEric Joyner case ICE_CEE_DCBX_OUI: 71971d10453SEric Joyner ice_parse_cee_tlv(tlv, dcbcfg); 72071d10453SEric Joyner break; 72171d10453SEric Joyner default: 72271d10453SEric Joyner break; 72371d10453SEric Joyner } 72471d10453SEric Joyner } 72571d10453SEric Joyner 72671d10453SEric Joyner /** 72771d10453SEric Joyner * ice_lldp_to_dcb_cfg 72871d10453SEric Joyner * @lldpmib: LLDPDU to be parsed 72971d10453SEric Joyner * @dcbcfg: store for LLDPDU data 73071d10453SEric Joyner * 73171d10453SEric Joyner * Parse DCB configuration from the LLDPDU 73271d10453SEric Joyner */ 733*f2635e84SEric Joyner int ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg) 73471d10453SEric Joyner { 73571d10453SEric Joyner struct ice_lldp_org_tlv *tlv; 73671d10453SEric Joyner u16 offset = 0; 737*f2635e84SEric Joyner int ret = 0; 73871d10453SEric Joyner u16 typelen; 73971d10453SEric Joyner u16 type; 74071d10453SEric Joyner u16 len; 74171d10453SEric Joyner 74271d10453SEric Joyner if (!lldpmib || !dcbcfg) 74371d10453SEric Joyner return ICE_ERR_PARAM; 74471d10453SEric Joyner 74571d10453SEric Joyner /* set to the start of LLDPDU */ 74671d10453SEric Joyner lldpmib += ETH_HEADER_LEN; 74771d10453SEric Joyner tlv = (struct ice_lldp_org_tlv *)lldpmib; 74871d10453SEric Joyner while (1) { 74971d10453SEric Joyner typelen = NTOHS(tlv->typelen); 75071d10453SEric Joyner type = ((typelen & ICE_LLDP_TLV_TYPE_M) >> ICE_LLDP_TLV_TYPE_S); 75171d10453SEric Joyner len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S); 75271d10453SEric Joyner offset += sizeof(typelen) + len; 75371d10453SEric Joyner 75471d10453SEric Joyner /* END TLV or beyond LLDPDU size */ 75571d10453SEric Joyner if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE) 75671d10453SEric Joyner break; 75771d10453SEric Joyner 75871d10453SEric Joyner switch (type) { 75971d10453SEric Joyner case ICE_TLV_TYPE_ORG: 76071d10453SEric Joyner ice_parse_org_tlv(tlv, dcbcfg); 76171d10453SEric Joyner break; 76271d10453SEric Joyner default: 76371d10453SEric Joyner break; 76471d10453SEric Joyner } 76571d10453SEric Joyner 76671d10453SEric Joyner /* Move to next TLV */ 76771d10453SEric Joyner tlv = (struct ice_lldp_org_tlv *) 76871d10453SEric Joyner ((char *)tlv + sizeof(tlv->typelen) + len); 76971d10453SEric Joyner } 77071d10453SEric Joyner 77171d10453SEric Joyner return ret; 77271d10453SEric Joyner } 77371d10453SEric Joyner 77471d10453SEric Joyner /** 77571d10453SEric Joyner * ice_aq_get_dcb_cfg 77671d10453SEric Joyner * @hw: pointer to the HW struct 77771d10453SEric Joyner * @mib_type: MIB type for the query 77871d10453SEric Joyner * @bridgetype: bridge type for the query (remote) 77971d10453SEric Joyner * @dcbcfg: store for LLDPDU data 78071d10453SEric Joyner * 78171d10453SEric Joyner * Query DCB configuration from the firmware 78271d10453SEric Joyner */ 783*f2635e84SEric Joyner int 78471d10453SEric Joyner ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype, 78571d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 78671d10453SEric Joyner { 78771d10453SEric Joyner u8 *lldpmib; 788*f2635e84SEric Joyner int ret; 78971d10453SEric Joyner 79071d10453SEric Joyner /* Allocate the LLDPDU */ 79171d10453SEric Joyner lldpmib = (u8 *)ice_malloc(hw, ICE_LLDPDU_SIZE); 79271d10453SEric Joyner if (!lldpmib) 79371d10453SEric Joyner return ICE_ERR_NO_MEMORY; 79471d10453SEric Joyner 79571d10453SEric Joyner ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib, 79671d10453SEric Joyner ICE_LLDPDU_SIZE, NULL, NULL, NULL); 79771d10453SEric Joyner 798*f2635e84SEric Joyner if (!ret) 79971d10453SEric Joyner /* Parse LLDP MIB to get DCB configuration */ 80071d10453SEric Joyner ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg); 80171d10453SEric Joyner 80271d10453SEric Joyner ice_free(hw, lldpmib); 80371d10453SEric Joyner 80471d10453SEric Joyner return ret; 80571d10453SEric Joyner } 80671d10453SEric Joyner 80771d10453SEric Joyner /** 80871d10453SEric Joyner * ice_aq_dcb_ignore_pfc - Ignore PFC for given TCs 80971d10453SEric Joyner * @hw: pointer to the HW struct 81071d10453SEric Joyner * @tcmap: TC map for request/release any ignore PFC condition 81171d10453SEric Joyner * @request: request (true) or release (false) ignore PFC condition 81271d10453SEric Joyner * @tcmap_ret: return TCs for which PFC is currently ignored 81371d10453SEric Joyner * @cd: pointer to command details structure or NULL 81471d10453SEric Joyner * 81571d10453SEric Joyner * This sends out request/release to ignore PFC condition for a TC. 81671d10453SEric Joyner * It will return the TCs for which PFC is currently ignored. (0x0301) 81771d10453SEric Joyner */ 818*f2635e84SEric Joyner int 81971d10453SEric Joyner ice_aq_dcb_ignore_pfc(struct ice_hw *hw, u8 tcmap, bool request, u8 *tcmap_ret, 82071d10453SEric Joyner struct ice_sq_cd *cd) 82171d10453SEric Joyner { 82271d10453SEric Joyner struct ice_aqc_pfc_ignore *cmd; 82371d10453SEric Joyner struct ice_aq_desc desc; 824*f2635e84SEric Joyner int status; 82571d10453SEric Joyner 82671d10453SEric Joyner cmd = &desc.params.pfc_ignore; 82771d10453SEric Joyner 82871d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_pfc_ignore); 82971d10453SEric Joyner 83071d10453SEric Joyner if (request) 83171d10453SEric Joyner cmd->cmd_flags = ICE_AQC_PFC_IGNORE_SET; 83271d10453SEric Joyner 83371d10453SEric Joyner cmd->tc_bitmap = tcmap; 83471d10453SEric Joyner 83571d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 83671d10453SEric Joyner 83771d10453SEric Joyner if (!status && tcmap_ret) 83871d10453SEric Joyner *tcmap_ret = cmd->tc_bitmap; 83971d10453SEric Joyner 84071d10453SEric Joyner return status; 84171d10453SEric Joyner } 84271d10453SEric Joyner 84371d10453SEric Joyner /** 84471d10453SEric Joyner * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW 84571d10453SEric Joyner * @hw: pointer to the HW struct 84671d10453SEric Joyner * @start_dcbx_agent: True if DCBX Agent needs to be started 84771d10453SEric Joyner * False if DCBX Agent needs to be stopped 84871d10453SEric Joyner * @dcbx_agent_status: FW indicates back the DCBX agent status 84971d10453SEric Joyner * True if DCBX Agent is active 85071d10453SEric Joyner * False if DCBX Agent is stopped 85171d10453SEric Joyner * @cd: pointer to command details structure or NULL 85271d10453SEric Joyner * 85371d10453SEric Joyner * Start/Stop the embedded dcbx Agent. In case that this wrapper function 854*f2635e84SEric Joyner * returns 0, caller will need to check if FW returns back the same 85571d10453SEric Joyner * value as stated in dcbx_agent_status, and react accordingly. (0x0A09) 85671d10453SEric Joyner */ 857*f2635e84SEric Joyner int 85871d10453SEric Joyner ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent, 85971d10453SEric Joyner bool *dcbx_agent_status, struct ice_sq_cd *cd) 86071d10453SEric Joyner { 86171d10453SEric Joyner struct ice_aqc_lldp_stop_start_specific_agent *cmd; 8628923de59SPiotr Kubaj enum ice_adminq_opc opcode; 86371d10453SEric Joyner struct ice_aq_desc desc; 864*f2635e84SEric Joyner int status; 86571d10453SEric Joyner 86671d10453SEric Joyner cmd = &desc.params.lldp_agent_ctrl; 86771d10453SEric Joyner 86871d10453SEric Joyner opcode = ice_aqc_opc_lldp_stop_start_specific_agent; 86971d10453SEric Joyner 87071d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, opcode); 87171d10453SEric Joyner 87271d10453SEric Joyner if (start_dcbx_agent) 87371d10453SEric Joyner cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX; 87471d10453SEric Joyner 87571d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 87671d10453SEric Joyner 87771d10453SEric Joyner *dcbx_agent_status = false; 87871d10453SEric Joyner 879*f2635e84SEric Joyner if (!status && 88071d10453SEric Joyner cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX) 88171d10453SEric Joyner *dcbx_agent_status = true; 88271d10453SEric Joyner 88371d10453SEric Joyner return status; 88471d10453SEric Joyner } 88571d10453SEric Joyner 88671d10453SEric Joyner /** 88771d10453SEric Joyner * ice_aq_get_cee_dcb_cfg 88871d10453SEric Joyner * @hw: pointer to the HW struct 88971d10453SEric Joyner * @buff: response buffer that stores CEE operational configuration 89071d10453SEric Joyner * @cd: pointer to command details structure or NULL 89171d10453SEric Joyner * 89271d10453SEric Joyner * Get CEE DCBX mode operational configuration from firmware (0x0A07) 89371d10453SEric Joyner */ 894*f2635e84SEric Joyner int 89571d10453SEric Joyner ice_aq_get_cee_dcb_cfg(struct ice_hw *hw, 89671d10453SEric Joyner struct ice_aqc_get_cee_dcb_cfg_resp *buff, 89771d10453SEric Joyner struct ice_sq_cd *cd) 89871d10453SEric Joyner { 89971d10453SEric Joyner struct ice_aq_desc desc; 90071d10453SEric Joyner 90171d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg); 90271d10453SEric Joyner 90371d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd); 90471d10453SEric Joyner } 90571d10453SEric Joyner 90671d10453SEric Joyner /** 90771d10453SEric Joyner * ice_aq_query_pfc_mode - Query PFC mode 90871d10453SEric Joyner * @hw: pointer to the HW struct 90971d10453SEric Joyner * @pfcmode_ret: Return PFC mode 91071d10453SEric Joyner * @cd: pointer to command details structure or NULL 91171d10453SEric Joyner * 91271d10453SEric Joyner * This will return an indication if DSCP-based PFC or VLAN-based PFC 91371d10453SEric Joyner * is enabled. (0x0302) 91471d10453SEric Joyner */ 915*f2635e84SEric Joyner int 91671d10453SEric Joyner ice_aq_query_pfc_mode(struct ice_hw *hw, u8 *pfcmode_ret, struct ice_sq_cd *cd) 91771d10453SEric Joyner { 91871d10453SEric Joyner struct ice_aqc_set_query_pfc_mode *cmd; 91971d10453SEric Joyner struct ice_aq_desc desc; 920*f2635e84SEric Joyner int status; 92171d10453SEric Joyner 92271d10453SEric Joyner cmd = &desc.params.set_query_pfc_mode; 92371d10453SEric Joyner 92471d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_pfc_mode); 92571d10453SEric Joyner 92671d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 92771d10453SEric Joyner 92871d10453SEric Joyner if (!status) 92971d10453SEric Joyner *pfcmode_ret = cmd->pfc_mode; 93071d10453SEric Joyner 93171d10453SEric Joyner return status; 93271d10453SEric Joyner } 93371d10453SEric Joyner 93471d10453SEric Joyner /** 93571d10453SEric Joyner * ice_aq_set_pfc_mode - Set PFC mode 93671d10453SEric Joyner * @hw: pointer to the HW struct 93756429daeSEric Joyner * @pfc_mode: value of PFC mode to set 93871d10453SEric Joyner * @cd: pointer to command details structure or NULL 93971d10453SEric Joyner * 94071d10453SEric Joyner * This AQ call configures the PFC mdoe to DSCP-based PFC mode or VLAN 94171d10453SEric Joyner * -based PFC (0x0303) 94271d10453SEric Joyner */ 943*f2635e84SEric Joyner int 94456429daeSEric Joyner ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd) 94571d10453SEric Joyner { 94671d10453SEric Joyner struct ice_aqc_set_query_pfc_mode *cmd; 94771d10453SEric Joyner struct ice_aq_desc desc; 948*f2635e84SEric Joyner int status; 94971d10453SEric Joyner 95056429daeSEric Joyner if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC) 95171d10453SEric Joyner return ICE_ERR_PARAM; 95271d10453SEric Joyner 95371d10453SEric Joyner cmd = &desc.params.set_query_pfc_mode; 95471d10453SEric Joyner 95571d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode); 95671d10453SEric Joyner 95756429daeSEric Joyner cmd->pfc_mode = pfc_mode; 95871d10453SEric Joyner 95971d10453SEric Joyner status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 96056429daeSEric Joyner if (status) 96171d10453SEric Joyner return status; 96256429daeSEric Joyner 96356429daeSEric Joyner /* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is 96456429daeSEric Joyner * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has 96556429daeSEric Joyner * been executed, check if cmd->pfc_mode is what was requested. If not, 96656429daeSEric Joyner * return an error. 96756429daeSEric Joyner */ 96856429daeSEric Joyner if (cmd->pfc_mode != pfc_mode) 96956429daeSEric Joyner return ICE_ERR_NOT_SUPPORTED; 97056429daeSEric Joyner 971*f2635e84SEric Joyner return 0; 97271d10453SEric Joyner } 97371d10453SEric Joyner 97471d10453SEric Joyner /** 97571d10453SEric Joyner * ice_aq_set_dcb_parameters - Set DCB parameters 97671d10453SEric Joyner * @hw: pointer to the HW struct 97771d10453SEric Joyner * @dcb_enable: True if DCB configuration needs to be applied 97871d10453SEric Joyner * @cd: pointer to command details structure or NULL 97971d10453SEric Joyner * 98071d10453SEric Joyner * This AQ command will tell FW if it will apply or not apply the default DCB 98171d10453SEric Joyner * configuration when link up (0x0306). 98271d10453SEric Joyner */ 983*f2635e84SEric Joyner int 98471d10453SEric Joyner ice_aq_set_dcb_parameters(struct ice_hw *hw, bool dcb_enable, 98571d10453SEric Joyner struct ice_sq_cd *cd) 98671d10453SEric Joyner { 98771d10453SEric Joyner struct ice_aqc_set_dcb_params *cmd; 98871d10453SEric Joyner struct ice_aq_desc desc; 98971d10453SEric Joyner 99071d10453SEric Joyner cmd = &desc.params.set_dcb_params; 99171d10453SEric Joyner 99271d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_dcb_params); 99371d10453SEric Joyner 99471d10453SEric Joyner cmd->valid_flags = ICE_AQC_LINK_UP_DCB_CFG_VALID; 99571d10453SEric Joyner if (dcb_enable) 99671d10453SEric Joyner cmd->cmd_flags = ICE_AQC_LINK_UP_DCB_CFG; 99771d10453SEric Joyner 99871d10453SEric Joyner return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 99971d10453SEric Joyner } 100071d10453SEric Joyner 100171d10453SEric Joyner /** 100271d10453SEric Joyner * ice_cee_to_dcb_cfg 100371d10453SEric Joyner * @cee_cfg: pointer to CEE configuration struct 1004d08b8680SEric Joyner * @pi: port information structure 100571d10453SEric Joyner * 100671d10453SEric Joyner * Convert CEE configuration from firmware to DCB configuration 100771d10453SEric Joyner */ 100871d10453SEric Joyner static void 100971d10453SEric Joyner ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, 1010d08b8680SEric Joyner struct ice_port_info *pi) 101171d10453SEric Joyner { 101271d10453SEric Joyner u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status); 101371d10453SEric Joyner u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift; 1014d08b8680SEric Joyner u8 i, j, err, sync, oper, app_index, ice_app_sel_type; 101571d10453SEric Joyner u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio); 101671d10453SEric Joyner u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; 1017d08b8680SEric Joyner struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg; 101871d10453SEric Joyner u16 ice_app_prot_id_type; 101971d10453SEric Joyner 1020d08b8680SEric Joyner dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 1021d08b8680SEric Joyner dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE; 1022d08b8680SEric Joyner dcbcfg->tlv_status = tlv_status; 1023d08b8680SEric Joyner 1024d08b8680SEric Joyner /* CEE PG data */ 102571d10453SEric Joyner dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; 102671d10453SEric Joyner 102771d10453SEric Joyner /* Note that the FW creates the oper_prio_tc nibbles reversed 102871d10453SEric Joyner * from those in the CEE Priority Group sub-TLV. 102971d10453SEric Joyner */ 103071d10453SEric Joyner for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 103171d10453SEric Joyner dcbcfg->etscfg.prio_table[i * 2] = 103271d10453SEric Joyner ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_0_M) >> 103371d10453SEric Joyner ICE_CEE_PGID_PRIO_0_S); 103471d10453SEric Joyner dcbcfg->etscfg.prio_table[i * 2 + 1] = 103571d10453SEric Joyner ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_1_M) >> 103671d10453SEric Joyner ICE_CEE_PGID_PRIO_1_S); 103771d10453SEric Joyner } 103871d10453SEric Joyner 103971d10453SEric Joyner ice_for_each_traffic_class(i) { 104071d10453SEric Joyner dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; 104171d10453SEric Joyner 104271d10453SEric Joyner if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) { 104371d10453SEric Joyner /* Map it to next empty TC */ 104471d10453SEric Joyner dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1; 104571d10453SEric Joyner dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT; 104671d10453SEric Joyner } else { 104771d10453SEric Joyner dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS; 104871d10453SEric Joyner } 104971d10453SEric Joyner } 105071d10453SEric Joyner 1051d08b8680SEric Joyner /* CEE PFC data */ 105271d10453SEric Joyner dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en; 105371d10453SEric Joyner dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS; 105471d10453SEric Joyner 1055d08b8680SEric Joyner /* CEE APP TLV data */ 1056d08b8680SEric Joyner if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 1057d08b8680SEric Joyner cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg; 1058d08b8680SEric Joyner else 1059d08b8680SEric Joyner cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg; 1060d08b8680SEric Joyner 106171d10453SEric Joyner app_index = 0; 106271d10453SEric Joyner for (i = 0; i < 3; i++) { 106371d10453SEric Joyner if (i == 0) { 106471d10453SEric Joyner /* FCoE APP */ 106571d10453SEric Joyner ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M; 106671d10453SEric Joyner ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S; 106771d10453SEric Joyner ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M; 106871d10453SEric Joyner ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S; 106971d10453SEric Joyner ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 107071d10453SEric Joyner ice_app_prot_id_type = ICE_APP_PROT_ID_FCOE; 107171d10453SEric Joyner } else if (i == 1) { 107271d10453SEric Joyner /* iSCSI APP */ 107371d10453SEric Joyner ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M; 107471d10453SEric Joyner ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S; 107571d10453SEric Joyner ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M; 107671d10453SEric Joyner ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S; 107771d10453SEric Joyner ice_app_sel_type = ICE_APP_SEL_TCPIP; 107871d10453SEric Joyner ice_app_prot_id_type = ICE_APP_PROT_ID_ISCSI; 1079d08b8680SEric Joyner 1080d08b8680SEric Joyner for (j = 0; j < cmp_dcbcfg->numapps; j++) { 1081d08b8680SEric Joyner u16 prot_id = cmp_dcbcfg->app[j].prot_id; 1082d08b8680SEric Joyner u8 sel = cmp_dcbcfg->app[j].selector; 1083d08b8680SEric Joyner 1084d08b8680SEric Joyner if (sel == ICE_APP_SEL_TCPIP && 1085d08b8680SEric Joyner (prot_id == ICE_APP_PROT_ID_ISCSI || 1086d08b8680SEric Joyner prot_id == ICE_APP_PROT_ID_ISCSI_860)) { 1087d08b8680SEric Joyner ice_app_prot_id_type = prot_id; 1088d08b8680SEric Joyner break; 1089d08b8680SEric Joyner } 1090d08b8680SEric Joyner } 109171d10453SEric Joyner } else { 109271d10453SEric Joyner /* FIP APP */ 109371d10453SEric Joyner ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M; 109471d10453SEric Joyner ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S; 109571d10453SEric Joyner ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M; 109671d10453SEric Joyner ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S; 109771d10453SEric Joyner ice_app_sel_type = ICE_APP_SEL_ETHTYPE; 109871d10453SEric Joyner ice_app_prot_id_type = ICE_APP_PROT_ID_FIP; 109971d10453SEric Joyner } 110071d10453SEric Joyner 110171d10453SEric Joyner status = (tlv_status & ice_aqc_cee_status_mask) >> 110271d10453SEric Joyner ice_aqc_cee_status_shift; 110371d10453SEric Joyner err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0; 110471d10453SEric Joyner sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0; 110571d10453SEric Joyner oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0; 110671d10453SEric Joyner /* Add FCoE/iSCSI/FIP APP if Error is False and 110771d10453SEric Joyner * Oper/Sync is True 110871d10453SEric Joyner */ 110971d10453SEric Joyner if (!err && sync && oper) { 111071d10453SEric Joyner dcbcfg->app[app_index].priority = 11118923de59SPiotr Kubaj (u8)((app_prio & ice_aqc_cee_app_mask) >> 11128923de59SPiotr Kubaj ice_aqc_cee_app_shift); 111371d10453SEric Joyner dcbcfg->app[app_index].selector = ice_app_sel_type; 111471d10453SEric Joyner dcbcfg->app[app_index].prot_id = ice_app_prot_id_type; 111571d10453SEric Joyner app_index++; 111671d10453SEric Joyner } 111771d10453SEric Joyner } 111871d10453SEric Joyner 111971d10453SEric Joyner dcbcfg->numapps = app_index; 112071d10453SEric Joyner } 112171d10453SEric Joyner 112271d10453SEric Joyner /** 112356429daeSEric Joyner * ice_get_ieee_or_cee_dcb_cfg 112471d10453SEric Joyner * @pi: port information structure 112571d10453SEric Joyner * @dcbx_mode: mode of DCBX (IEEE or CEE) 112671d10453SEric Joyner * 112771d10453SEric Joyner * Get IEEE or CEE mode DCB configuration from the Firmware 112871d10453SEric Joyner */ 1129*f2635e84SEric Joyner STATIC int 113071d10453SEric Joyner ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode) 113171d10453SEric Joyner { 113271d10453SEric Joyner struct ice_dcbx_cfg *dcbx_cfg = NULL; 1133*f2635e84SEric Joyner int ret; 113471d10453SEric Joyner 113571d10453SEric Joyner if (!pi) 113671d10453SEric Joyner return ICE_ERR_PARAM; 113771d10453SEric Joyner 113871d10453SEric Joyner if (dcbx_mode == ICE_DCBX_MODE_IEEE) 11397d7af7f8SEric Joyner dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 114071d10453SEric Joyner else if (dcbx_mode == ICE_DCBX_MODE_CEE) 11417d7af7f8SEric Joyner dcbx_cfg = &pi->qos_cfg.desired_dcbx_cfg; 114271d10453SEric Joyner 114371d10453SEric Joyner /* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE 114471d10453SEric Joyner * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE 114571d10453SEric Joyner */ 114671d10453SEric Joyner ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL, 114771d10453SEric Joyner ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 114871d10453SEric Joyner if (ret) 114971d10453SEric Joyner goto out; 115071d10453SEric Joyner 115171d10453SEric Joyner /* Get Remote DCB Config */ 11527d7af7f8SEric Joyner dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg; 115371d10453SEric Joyner ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE, 115471d10453SEric Joyner ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg); 115571d10453SEric Joyner /* Don't treat ENOENT as an error for Remote MIBs */ 115671d10453SEric Joyner if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 1157*f2635e84SEric Joyner ret = 0; 115871d10453SEric Joyner 115971d10453SEric Joyner out: 116071d10453SEric Joyner return ret; 116171d10453SEric Joyner } 116271d10453SEric Joyner 116371d10453SEric Joyner /** 116471d10453SEric Joyner * ice_get_dcb_cfg 116571d10453SEric Joyner * @pi: port information structure 116671d10453SEric Joyner * 116771d10453SEric Joyner * Get DCB configuration from the Firmware 116871d10453SEric Joyner */ 1169*f2635e84SEric Joyner int ice_get_dcb_cfg(struct ice_port_info *pi) 117071d10453SEric Joyner { 117171d10453SEric Joyner struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg; 117271d10453SEric Joyner struct ice_dcbx_cfg *dcbx_cfg; 1173*f2635e84SEric Joyner int ret; 117471d10453SEric Joyner 117571d10453SEric Joyner if (!pi) 117671d10453SEric Joyner return ICE_ERR_PARAM; 117771d10453SEric Joyner 117871d10453SEric Joyner ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL); 1179*f2635e84SEric Joyner if (!ret) { 118071d10453SEric Joyner /* CEE mode */ 118171d10453SEric Joyner ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE); 1182d08b8680SEric Joyner ice_cee_to_dcb_cfg(&cee_cfg, pi); 118371d10453SEric Joyner } else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) { 118471d10453SEric Joyner /* CEE mode not enabled try querying IEEE data */ 11857d7af7f8SEric Joyner dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 118671d10453SEric Joyner dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE; 118771d10453SEric Joyner ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE); 118871d10453SEric Joyner } 118971d10453SEric Joyner 119071d10453SEric Joyner return ret; 119171d10453SEric Joyner } 119271d10453SEric Joyner 119371d10453SEric Joyner /** 11948923de59SPiotr Kubaj * ice_get_dcb_cfg_from_mib_change 11958923de59SPiotr Kubaj * @pi: port information structure 11968923de59SPiotr Kubaj * @event: pointer to the admin queue receive event 11978923de59SPiotr Kubaj * 11988923de59SPiotr Kubaj * Set DCB configuration from received MIB Change event 11998923de59SPiotr Kubaj */ 12008923de59SPiotr Kubaj void ice_get_dcb_cfg_from_mib_change(struct ice_port_info *pi, 12018923de59SPiotr Kubaj struct ice_rq_event_info *event) 12028923de59SPiotr Kubaj { 12038923de59SPiotr Kubaj struct ice_dcbx_cfg *dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; 12048923de59SPiotr Kubaj struct ice_aqc_lldp_get_mib *mib; 12058923de59SPiotr Kubaj u8 change_type, dcbx_mode; 12068923de59SPiotr Kubaj 12078923de59SPiotr Kubaj mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw; 12088923de59SPiotr Kubaj 12098923de59SPiotr Kubaj change_type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M; 12108923de59SPiotr Kubaj if (change_type == ICE_AQ_LLDP_MIB_REMOTE) 12118923de59SPiotr Kubaj dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg; 12128923de59SPiotr Kubaj 12138923de59SPiotr Kubaj dcbx_mode = ((mib->type & ICE_AQ_LLDP_DCBX_M) >> 12148923de59SPiotr Kubaj ICE_AQ_LLDP_DCBX_S); 12158923de59SPiotr Kubaj 12168923de59SPiotr Kubaj switch (dcbx_mode) { 12178923de59SPiotr Kubaj case ICE_AQ_LLDP_DCBX_IEEE: 12188923de59SPiotr Kubaj dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE; 12198923de59SPiotr Kubaj ice_lldp_to_dcb_cfg(event->msg_buf, dcbx_cfg); 12208923de59SPiotr Kubaj break; 12218923de59SPiotr Kubaj 12228923de59SPiotr Kubaj case ICE_AQ_LLDP_DCBX_CEE: 12238923de59SPiotr Kubaj pi->qos_cfg.desired_dcbx_cfg = pi->qos_cfg.local_dcbx_cfg; 12248923de59SPiotr Kubaj ice_cee_to_dcb_cfg((struct ice_aqc_get_cee_dcb_cfg_resp *) 12258923de59SPiotr Kubaj event->msg_buf, pi); 12268923de59SPiotr Kubaj break; 12278923de59SPiotr Kubaj } 12288923de59SPiotr Kubaj } 12298923de59SPiotr Kubaj 12308923de59SPiotr Kubaj /** 123171d10453SEric Joyner * ice_init_dcb 123271d10453SEric Joyner * @hw: pointer to the HW struct 123371d10453SEric Joyner * @enable_mib_change: enable MIB change event 123471d10453SEric Joyner * 123571d10453SEric Joyner * Update DCB configuration from the Firmware 123671d10453SEric Joyner */ 1237*f2635e84SEric Joyner int ice_init_dcb(struct ice_hw *hw, bool enable_mib_change) 123871d10453SEric Joyner { 12397d7af7f8SEric Joyner struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg; 1240*f2635e84SEric Joyner int ret = 0; 124171d10453SEric Joyner 124271d10453SEric Joyner if (!hw->func_caps.common_cap.dcb) 124371d10453SEric Joyner return ICE_ERR_NOT_SUPPORTED; 124471d10453SEric Joyner 12457d7af7f8SEric Joyner qos_cfg->is_sw_lldp = true; 124671d10453SEric Joyner 124771d10453SEric Joyner /* Get DCBX status */ 12487d7af7f8SEric Joyner qos_cfg->dcbx_status = ice_get_dcbx_status(hw); 124971d10453SEric Joyner 12507d7af7f8SEric Joyner if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DONE || 12517d7af7f8SEric Joyner qos_cfg->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS || 12527d7af7f8SEric Joyner qos_cfg->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { 125371d10453SEric Joyner /* Get current DCBX configuration */ 12547d7af7f8SEric Joyner ret = ice_get_dcb_cfg(hw->port_info); 125571d10453SEric Joyner if (ret) 125671d10453SEric Joyner return ret; 12577d7af7f8SEric Joyner qos_cfg->is_sw_lldp = false; 12587d7af7f8SEric Joyner } else if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) { 125971d10453SEric Joyner return ICE_ERR_NOT_READY; 126071d10453SEric Joyner } 126171d10453SEric Joyner 126271d10453SEric Joyner /* Configure the LLDP MIB change event */ 126371d10453SEric Joyner if (enable_mib_change) { 126471d10453SEric Joyner ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL); 126571d10453SEric Joyner if (ret) 12667d7af7f8SEric Joyner qos_cfg->is_sw_lldp = true; 126771d10453SEric Joyner } 126871d10453SEric Joyner 126971d10453SEric Joyner return ret; 127071d10453SEric Joyner } 127171d10453SEric Joyner 127271d10453SEric Joyner /** 127371d10453SEric Joyner * ice_cfg_lldp_mib_change 127471d10453SEric Joyner * @hw: pointer to the HW struct 127571d10453SEric Joyner * @ena_mib: enable/disable MIB change event 127671d10453SEric Joyner * 127771d10453SEric Joyner * Configure (disable/enable) MIB 127871d10453SEric Joyner */ 1279*f2635e84SEric Joyner int ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib) 128071d10453SEric Joyner { 12817d7af7f8SEric Joyner struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg; 1282*f2635e84SEric Joyner int ret; 128371d10453SEric Joyner 128471d10453SEric Joyner if (!hw->func_caps.common_cap.dcb) 128571d10453SEric Joyner return ICE_ERR_NOT_SUPPORTED; 128671d10453SEric Joyner 128771d10453SEric Joyner /* Get DCBX status */ 12887d7af7f8SEric Joyner qos_cfg->dcbx_status = ice_get_dcbx_status(hw); 128971d10453SEric Joyner 12907d7af7f8SEric Joyner if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) 129171d10453SEric Joyner return ICE_ERR_NOT_READY; 129271d10453SEric Joyner 129371d10453SEric Joyner ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL); 129471d10453SEric Joyner if (!ret) 12957d7af7f8SEric Joyner qos_cfg->is_sw_lldp = !ena_mib; 129671d10453SEric Joyner 129771d10453SEric Joyner return ret; 129871d10453SEric Joyner } 129971d10453SEric Joyner 130071d10453SEric Joyner /** 130171d10453SEric Joyner * ice_add_ieee_ets_common_tlv 130271d10453SEric Joyner * @buf: Data buffer to be populated with ice_dcb_ets_cfg data 130371d10453SEric Joyner * @ets_cfg: Container for ice_dcb_ets_cfg data 130471d10453SEric Joyner * 130571d10453SEric Joyner * Populate the TLV buffer with ice_dcb_ets_cfg data 130671d10453SEric Joyner */ 130771d10453SEric Joyner static void 130871d10453SEric Joyner ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg) 130971d10453SEric Joyner { 131071d10453SEric Joyner u8 priority0, priority1; 131171d10453SEric Joyner u8 offset = 0; 131271d10453SEric Joyner int i; 131371d10453SEric Joyner 131471d10453SEric Joyner /* Priority Assignment Table (4 octets) 131571d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 131671d10453SEric Joyner * ----------------------------------------- 131771d10453SEric Joyner * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| 131871d10453SEric Joyner * ----------------------------------------- 131971d10453SEric Joyner * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| 132071d10453SEric Joyner * ----------------------------------------- 132171d10453SEric Joyner */ 132271d10453SEric Joyner for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) { 132371d10453SEric Joyner priority0 = ets_cfg->prio_table[i * 2] & 0xF; 132471d10453SEric Joyner priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF; 132571d10453SEric Joyner buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1; 132671d10453SEric Joyner offset++; 132771d10453SEric Joyner } 132871d10453SEric Joyner 132971d10453SEric Joyner /* TC Bandwidth Table (8 octets) 133071d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 133171d10453SEric Joyner * --------------------------------- 133271d10453SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 133371d10453SEric Joyner * --------------------------------- 133471d10453SEric Joyner * 133571d10453SEric Joyner * TSA Assignment Table (8 octets) 133671d10453SEric Joyner * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 133771d10453SEric Joyner * --------------------------------- 133871d10453SEric Joyner * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| 133971d10453SEric Joyner * --------------------------------- 134071d10453SEric Joyner */ 134171d10453SEric Joyner ice_for_each_traffic_class(i) { 134271d10453SEric Joyner buf[offset] = ets_cfg->tcbwtable[i]; 134371d10453SEric Joyner buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i]; 134471d10453SEric Joyner offset++; 134571d10453SEric Joyner } 134671d10453SEric Joyner } 134771d10453SEric Joyner 134871d10453SEric Joyner /** 134971d10453SEric Joyner * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format 135071d10453SEric Joyner * @tlv: Fill the ETS config data in IEEE format 135171d10453SEric Joyner * @dcbcfg: Local store which holds the DCB Config 135271d10453SEric Joyner * 135371d10453SEric Joyner * Prepare IEEE 802.1Qaz ETS CFG TLV 135471d10453SEric Joyner */ 135571d10453SEric Joyner static void 135671d10453SEric Joyner ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 135771d10453SEric Joyner { 135871d10453SEric Joyner struct ice_dcb_ets_cfg *etscfg; 135971d10453SEric Joyner u8 *buf = tlv->tlvinfo; 136071d10453SEric Joyner u8 maxtcwilling = 0; 136171d10453SEric Joyner u32 ouisubtype; 136271d10453SEric Joyner u16 typelen; 136371d10453SEric Joyner 136471d10453SEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 136571d10453SEric Joyner ICE_IEEE_ETS_TLV_LEN); 136671d10453SEric Joyner tlv->typelen = HTONS(typelen); 136771d10453SEric Joyner 136871d10453SEric Joyner ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 136971d10453SEric Joyner ICE_IEEE_SUBTYPE_ETS_CFG); 137071d10453SEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 137171d10453SEric Joyner 137271d10453SEric Joyner /* First Octet post subtype 137371d10453SEric Joyner * -------------------------- 137471d10453SEric Joyner * |will-|CBS | Re- | Max | 137571d10453SEric Joyner * |ing | |served| TCs | 137671d10453SEric Joyner * -------------------------- 137771d10453SEric Joyner * |1bit | 1bit|3 bits|3bits| 137871d10453SEric Joyner */ 137971d10453SEric Joyner etscfg = &dcbcfg->etscfg; 138071d10453SEric Joyner if (etscfg->willing) 138171d10453SEric Joyner maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S); 138271d10453SEric Joyner maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 138371d10453SEric Joyner buf[0] = maxtcwilling; 138471d10453SEric Joyner 138571d10453SEric Joyner /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 138671d10453SEric Joyner ice_add_ieee_ets_common_tlv(&buf[1], etscfg); 138771d10453SEric Joyner } 138871d10453SEric Joyner 138971d10453SEric Joyner /** 139071d10453SEric Joyner * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format 139171d10453SEric Joyner * @tlv: Fill ETS Recommended TLV in IEEE format 139271d10453SEric Joyner * @dcbcfg: Local store which holds the DCB Config 139371d10453SEric Joyner * 139471d10453SEric Joyner * Prepare IEEE 802.1Qaz ETS REC TLV 139571d10453SEric Joyner */ 139671d10453SEric Joyner static void 139771d10453SEric Joyner ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv, 139871d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 139971d10453SEric Joyner { 140071d10453SEric Joyner struct ice_dcb_ets_cfg *etsrec; 140171d10453SEric Joyner u8 *buf = tlv->tlvinfo; 140271d10453SEric Joyner u32 ouisubtype; 140371d10453SEric Joyner u16 typelen; 140471d10453SEric Joyner 140571d10453SEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 140671d10453SEric Joyner ICE_IEEE_ETS_TLV_LEN); 140771d10453SEric Joyner tlv->typelen = HTONS(typelen); 140871d10453SEric Joyner 140971d10453SEric Joyner ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 141071d10453SEric Joyner ICE_IEEE_SUBTYPE_ETS_REC); 141171d10453SEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 141271d10453SEric Joyner 141371d10453SEric Joyner etsrec = &dcbcfg->etsrec; 141471d10453SEric Joyner 141571d10453SEric Joyner /* First Octet is reserved */ 141671d10453SEric Joyner /* Begin adding at Priority Assignment Table (offset 1 in buf) */ 141771d10453SEric Joyner ice_add_ieee_ets_common_tlv(&buf[1], etsrec); 141871d10453SEric Joyner } 141971d10453SEric Joyner 142071d10453SEric Joyner /** 142171d10453SEric Joyner * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format 142271d10453SEric Joyner * @tlv: Fill PFC TLV in IEEE format 142371d10453SEric Joyner * @dcbcfg: Local store which holds the PFC CFG data 142471d10453SEric Joyner * 142571d10453SEric Joyner * Prepare IEEE 802.1Qaz PFC CFG TLV 142671d10453SEric Joyner */ 142771d10453SEric Joyner static void 142871d10453SEric Joyner ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 142971d10453SEric Joyner { 143071d10453SEric Joyner u8 *buf = tlv->tlvinfo; 143171d10453SEric Joyner u32 ouisubtype; 143271d10453SEric Joyner u16 typelen; 143371d10453SEric Joyner 143471d10453SEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 143571d10453SEric Joyner ICE_IEEE_PFC_TLV_LEN); 143671d10453SEric Joyner tlv->typelen = HTONS(typelen); 143771d10453SEric Joyner 143871d10453SEric Joyner ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 143971d10453SEric Joyner ICE_IEEE_SUBTYPE_PFC_CFG); 144071d10453SEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 144171d10453SEric Joyner 144271d10453SEric Joyner /* ---------------------------------------- 144371d10453SEric Joyner * |will-|MBC | Re- | PFC | PFC Enable | 144471d10453SEric Joyner * |ing | |served| cap | | 144571d10453SEric Joyner * ----------------------------------------- 144671d10453SEric Joyner * |1bit | 1bit|2 bits|4bits| 1 octet | 144771d10453SEric Joyner */ 144871d10453SEric Joyner if (dcbcfg->pfc.willing) 144971d10453SEric Joyner buf[0] = BIT(ICE_IEEE_PFC_WILLING_S); 145071d10453SEric Joyner 145171d10453SEric Joyner if (dcbcfg->pfc.mbc) 145271d10453SEric Joyner buf[0] |= BIT(ICE_IEEE_PFC_MBC_S); 145371d10453SEric Joyner 145471d10453SEric Joyner buf[0] |= dcbcfg->pfc.pfccap & 0xF; 145571d10453SEric Joyner buf[1] = dcbcfg->pfc.pfcena; 145671d10453SEric Joyner } 145771d10453SEric Joyner 145871d10453SEric Joyner /** 145971d10453SEric Joyner * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format 146071d10453SEric Joyner * @tlv: Fill APP TLV in IEEE format 146171d10453SEric Joyner * @dcbcfg: Local store which holds the APP CFG data 146271d10453SEric Joyner * 146371d10453SEric Joyner * Prepare IEEE 802.1Qaz APP CFG TLV 146471d10453SEric Joyner */ 146571d10453SEric Joyner static void 146671d10453SEric Joyner ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv, 146771d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg) 146871d10453SEric Joyner { 146971d10453SEric Joyner u16 typelen, len, offset = 0; 147071d10453SEric Joyner u8 priority, selector, i = 0; 147171d10453SEric Joyner u8 *buf = tlv->tlvinfo; 147271d10453SEric Joyner u32 ouisubtype; 147371d10453SEric Joyner 147471d10453SEric Joyner /* No APP TLVs then just return */ 147571d10453SEric Joyner if (dcbcfg->numapps == 0) 147671d10453SEric Joyner return; 147771d10453SEric Joyner ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) | 147871d10453SEric Joyner ICE_IEEE_SUBTYPE_APP_PRI); 147971d10453SEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 148071d10453SEric Joyner 148171d10453SEric Joyner /* Move offset to App Priority Table */ 148271d10453SEric Joyner offset++; 148371d10453SEric Joyner /* Application Priority Table (3 octets) 148471d10453SEric Joyner * Octets:| 1 | 2 | 3 | 148571d10453SEric Joyner * ----------------------------------------- 148671d10453SEric Joyner * |Priority|Rsrvd| Sel | Protocol ID | 148771d10453SEric Joyner * ----------------------------------------- 148871d10453SEric Joyner * Bits:|23 21|20 19|18 16|15 0| 148971d10453SEric Joyner * ----------------------------------------- 149071d10453SEric Joyner */ 149171d10453SEric Joyner while (i < dcbcfg->numapps) { 149271d10453SEric Joyner priority = dcbcfg->app[i].priority & 0x7; 149371d10453SEric Joyner selector = dcbcfg->app[i].selector & 0x7; 149471d10453SEric Joyner buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector; 149571d10453SEric Joyner buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF; 149671d10453SEric Joyner buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF; 149771d10453SEric Joyner /* Move to next app */ 149871d10453SEric Joyner offset += 3; 149971d10453SEric Joyner i++; 150071d10453SEric Joyner if (i >= ICE_DCBX_MAX_APPS) 150171d10453SEric Joyner break; 150271d10453SEric Joyner } 150371d10453SEric Joyner /* len includes size of ouisubtype + 1 reserved + 3*numapps */ 150471d10453SEric Joyner len = sizeof(tlv->ouisubtype) + 1 + (i * 3); 150571d10453SEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF)); 150671d10453SEric Joyner tlv->typelen = HTONS(typelen); 150771d10453SEric Joyner } 150871d10453SEric Joyner 150971d10453SEric Joyner /** 151056429daeSEric Joyner * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV 151156429daeSEric Joyner * @tlv: location to build the TLV data 151256429daeSEric Joyner * @dcbcfg: location of data to convert to TLV 151356429daeSEric Joyner */ 151456429daeSEric Joyner static void 151556429daeSEric Joyner ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 151656429daeSEric Joyner { 151756429daeSEric Joyner u8 *buf = tlv->tlvinfo; 151856429daeSEric Joyner u32 ouisubtype; 151956429daeSEric Joyner u16 typelen; 152056429daeSEric Joyner int i; 152156429daeSEric Joyner 152256429daeSEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 152356429daeSEric Joyner ICE_DSCP_UP_TLV_LEN); 152456429daeSEric Joyner tlv->typelen = HTONS(typelen); 152556429daeSEric Joyner 152656429daeSEric Joyner ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 152756429daeSEric Joyner ICE_DSCP_SUBTYPE_DSCP2UP); 152856429daeSEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 152956429daeSEric Joyner 153056429daeSEric Joyner /* bytes 0 - 63 - IPv4 DSCP2UP LUT */ 153156429daeSEric Joyner for (i = 0; i < ICE_DSCP_NUM_VAL; i++) { 153256429daeSEric Joyner /* IPv4 mapping */ 153356429daeSEric Joyner buf[i] = dcbcfg->dscp_map[i]; 153456429daeSEric Joyner /* IPv6 mapping */ 153556429daeSEric Joyner buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i]; 153656429daeSEric Joyner } 153756429daeSEric Joyner 153856429daeSEric Joyner /* byte 64 - IPv4 untagged traffic */ 153956429daeSEric Joyner buf[i] = 0; 154056429daeSEric Joyner 154156429daeSEric Joyner /* byte 144 - IPv6 untagged traffic */ 154256429daeSEric Joyner buf[i + ICE_DSCP_IPV6_OFFSET] = 0; 154356429daeSEric Joyner } 154456429daeSEric Joyner 154556429daeSEric Joyner #define ICE_BYTES_PER_TC 8 154656429daeSEric Joyner /** 154756429daeSEric Joyner * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV 154856429daeSEric Joyner * @tlv: location to build the TLV data 154956429daeSEric Joyner */ 155056429daeSEric Joyner static void 155156429daeSEric Joyner ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv) 155256429daeSEric Joyner { 155356429daeSEric Joyner u8 *buf = tlv->tlvinfo; 155456429daeSEric Joyner u32 ouisubtype; 155556429daeSEric Joyner u16 typelen; 155656429daeSEric Joyner 155756429daeSEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 155856429daeSEric Joyner ICE_DSCP_ENF_TLV_LEN); 155956429daeSEric Joyner tlv->typelen = HTONS(typelen); 156056429daeSEric Joyner 156156429daeSEric Joyner ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 156256429daeSEric Joyner ICE_DSCP_SUBTYPE_ENFORCE); 156356429daeSEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 156456429daeSEric Joyner 156556429daeSEric Joyner /* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */ 156656429daeSEric Joyner memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC)); 156756429daeSEric Joyner } 156856429daeSEric Joyner 156956429daeSEric Joyner /** 157056429daeSEric Joyner * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV 157156429daeSEric Joyner * @tlv: location to build the TLV data 157256429daeSEric Joyner * @dcbcfg: location of the data to convert to TLV 157356429daeSEric Joyner */ 157456429daeSEric Joyner static void 157556429daeSEric Joyner ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv, 157656429daeSEric Joyner struct ice_dcbx_cfg *dcbcfg) 157756429daeSEric Joyner { 157856429daeSEric Joyner struct ice_dcb_ets_cfg *etscfg; 157956429daeSEric Joyner u8 *buf = tlv->tlvinfo; 158056429daeSEric Joyner u32 ouisubtype; 158156429daeSEric Joyner u8 offset = 0; 158256429daeSEric Joyner u16 typelen; 158356429daeSEric Joyner int i; 158456429daeSEric Joyner 158556429daeSEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 158656429daeSEric Joyner ICE_DSCP_TC_BW_TLV_LEN); 158756429daeSEric Joyner tlv->typelen = HTONS(typelen); 158856429daeSEric Joyner 158956429daeSEric Joyner ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 159056429daeSEric Joyner ICE_DSCP_SUBTYPE_TCBW); 159156429daeSEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 159256429daeSEric Joyner 159356429daeSEric Joyner /* First Octect after subtype 159456429daeSEric Joyner * ---------------------------- 159556429daeSEric Joyner * | RSV | CBS | RSV | Max TCs | 159656429daeSEric Joyner * | 1b | 1b | 3b | 3b | 159756429daeSEric Joyner * ---------------------------- 159856429daeSEric Joyner */ 159956429daeSEric Joyner etscfg = &dcbcfg->etscfg; 160056429daeSEric Joyner buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M; 160156429daeSEric Joyner 160256429daeSEric Joyner /* bytes 1 - 4 reserved */ 160356429daeSEric Joyner offset = 5; 160456429daeSEric Joyner 160556429daeSEric Joyner /* TC BW table 160656429daeSEric Joyner * bytes 0 - 7 for TC 0 - 7 160756429daeSEric Joyner * 160856429daeSEric Joyner * TSA Assignment table 160956429daeSEric Joyner * bytes 8 - 15 for TC 0 - 7 161056429daeSEric Joyner */ 161156429daeSEric Joyner for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { 161256429daeSEric Joyner buf[offset] = etscfg->tcbwtable[i]; 161356429daeSEric Joyner buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i]; 161456429daeSEric Joyner offset++; 161556429daeSEric Joyner } 161656429daeSEric Joyner } 161756429daeSEric Joyner 161856429daeSEric Joyner /** 161956429daeSEric Joyner * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV 162056429daeSEric Joyner * @tlv: Fill PFC TLV in IEEE format 162156429daeSEric Joyner * @dcbcfg: Local store which holds the PFC CFG data 162256429daeSEric Joyner */ 162356429daeSEric Joyner static void 162456429daeSEric Joyner ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg) 162556429daeSEric Joyner { 162656429daeSEric Joyner u8 *buf = tlv->tlvinfo; 162756429daeSEric Joyner u32 ouisubtype; 162856429daeSEric Joyner u16 typelen; 162956429daeSEric Joyner 163056429daeSEric Joyner typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | 163156429daeSEric Joyner ICE_DSCP_PFC_TLV_LEN); 163256429daeSEric Joyner tlv->typelen = HTONS(typelen); 163356429daeSEric Joyner 163456429daeSEric Joyner ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) | 163556429daeSEric Joyner ICE_DSCP_SUBTYPE_PFC); 163656429daeSEric Joyner tlv->ouisubtype = HTONL(ouisubtype); 163756429daeSEric Joyner 163856429daeSEric Joyner buf[0] = dcbcfg->pfc.pfccap & 0xF; 16398923de59SPiotr Kubaj buf[1] = dcbcfg->pfc.pfcena; 164056429daeSEric Joyner } 164156429daeSEric Joyner 164256429daeSEric Joyner /** 164356429daeSEric Joyner * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs 164471d10453SEric Joyner * @tlv: Fill TLV data in IEEE format 164571d10453SEric Joyner * @dcbcfg: Local store which holds the DCB Config 164671d10453SEric Joyner * @tlvid: Type of IEEE TLV 164771d10453SEric Joyner * 164871d10453SEric Joyner * Add tlv information 164971d10453SEric Joyner */ 165071d10453SEric Joyner static void 165171d10453SEric Joyner ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg, 165271d10453SEric Joyner u16 tlvid) 165371d10453SEric Joyner { 165456429daeSEric Joyner if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) { 165571d10453SEric Joyner switch (tlvid) { 165671d10453SEric Joyner case ICE_IEEE_TLV_ID_ETS_CFG: 165771d10453SEric Joyner ice_add_ieee_ets_tlv(tlv, dcbcfg); 165871d10453SEric Joyner break; 165971d10453SEric Joyner case ICE_IEEE_TLV_ID_ETS_REC: 166071d10453SEric Joyner ice_add_ieee_etsrec_tlv(tlv, dcbcfg); 166171d10453SEric Joyner break; 166271d10453SEric Joyner case ICE_IEEE_TLV_ID_PFC_CFG: 166371d10453SEric Joyner ice_add_ieee_pfc_tlv(tlv, dcbcfg); 166471d10453SEric Joyner break; 166571d10453SEric Joyner case ICE_IEEE_TLV_ID_APP_PRI: 166671d10453SEric Joyner ice_add_ieee_app_pri_tlv(tlv, dcbcfg); 166771d10453SEric Joyner break; 166871d10453SEric Joyner default: 166971d10453SEric Joyner break; 167071d10453SEric Joyner } 167156429daeSEric Joyner } else { 167256429daeSEric Joyner /* pfc_mode == ICE_QOS_MODE_DSCP */ 167356429daeSEric Joyner switch (tlvid) { 167456429daeSEric Joyner case ICE_TLV_ID_DSCP_UP: 167556429daeSEric Joyner ice_add_dscp_up_tlv(tlv, dcbcfg); 167656429daeSEric Joyner break; 167756429daeSEric Joyner case ICE_TLV_ID_DSCP_ENF: 167856429daeSEric Joyner ice_add_dscp_enf_tlv(tlv); 167956429daeSEric Joyner break; 168056429daeSEric Joyner case ICE_TLV_ID_DSCP_TC_BW: 168156429daeSEric Joyner ice_add_dscp_tc_bw_tlv(tlv, dcbcfg); 168256429daeSEric Joyner break; 168356429daeSEric Joyner case ICE_TLV_ID_DSCP_TO_PFC: 168456429daeSEric Joyner ice_add_dscp_pfc_tlv(tlv, dcbcfg); 168556429daeSEric Joyner break; 168656429daeSEric Joyner default: 168756429daeSEric Joyner break; 168856429daeSEric Joyner } 168956429daeSEric Joyner } 169071d10453SEric Joyner } 169171d10453SEric Joyner 169271d10453SEric Joyner /** 169371d10453SEric Joyner * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format 169471d10453SEric Joyner * @lldpmib: pointer to the HW struct 169571d10453SEric Joyner * @miblen: length of LLDP MIB 169671d10453SEric Joyner * @dcbcfg: Local store which holds the DCB Config 169771d10453SEric Joyner * 169871d10453SEric Joyner * Convert the DCB configuration to MIB format 169971d10453SEric Joyner */ 170071d10453SEric Joyner void ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg) 170171d10453SEric Joyner { 170271d10453SEric Joyner u16 len, offset = 0, tlvid = ICE_TLV_ID_START; 170371d10453SEric Joyner struct ice_lldp_org_tlv *tlv; 170471d10453SEric Joyner u16 typelen; 170571d10453SEric Joyner 170671d10453SEric Joyner tlv = (struct ice_lldp_org_tlv *)lldpmib; 170771d10453SEric Joyner while (1) { 170871d10453SEric Joyner ice_add_dcb_tlv(tlv, dcbcfg, tlvid++); 170971d10453SEric Joyner typelen = NTOHS(tlv->typelen); 171071d10453SEric Joyner len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S; 171171d10453SEric Joyner if (len) 171271d10453SEric Joyner offset += len + 2; 171371d10453SEric Joyner /* END TLV or beyond LLDPDU size */ 171471d10453SEric Joyner if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU || 171571d10453SEric Joyner offset > ICE_LLDPDU_SIZE) 171671d10453SEric Joyner break; 171771d10453SEric Joyner /* Move to next TLV */ 171871d10453SEric Joyner if (len) 171971d10453SEric Joyner tlv = (struct ice_lldp_org_tlv *) 172071d10453SEric Joyner ((char *)tlv + sizeof(tlv->typelen) + len); 172171d10453SEric Joyner } 172271d10453SEric Joyner *miblen = offset; 172371d10453SEric Joyner } 172471d10453SEric Joyner 172571d10453SEric Joyner /** 172671d10453SEric Joyner * ice_set_dcb_cfg - Set the local LLDP MIB to FW 172771d10453SEric Joyner * @pi: port information structure 172871d10453SEric Joyner * 172971d10453SEric Joyner * Set DCB configuration to the Firmware 173071d10453SEric Joyner */ 1731*f2635e84SEric Joyner int ice_set_dcb_cfg(struct ice_port_info *pi) 173271d10453SEric Joyner { 173371d10453SEric Joyner u8 mib_type, *lldpmib = NULL; 173471d10453SEric Joyner struct ice_dcbx_cfg *dcbcfg; 173571d10453SEric Joyner struct ice_hw *hw; 173671d10453SEric Joyner u16 miblen; 1737*f2635e84SEric Joyner int ret; 173871d10453SEric Joyner 173971d10453SEric Joyner if (!pi) 174071d10453SEric Joyner return ICE_ERR_PARAM; 174171d10453SEric Joyner 174271d10453SEric Joyner hw = pi->hw; 174371d10453SEric Joyner 174471d10453SEric Joyner /* update the HW local config */ 17457d7af7f8SEric Joyner dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 174671d10453SEric Joyner /* Allocate the LLDPDU */ 174771d10453SEric Joyner lldpmib = (u8 *)ice_malloc(hw, ICE_LLDPDU_SIZE); 174871d10453SEric Joyner if (!lldpmib) 174971d10453SEric Joyner return ICE_ERR_NO_MEMORY; 175071d10453SEric Joyner 175171d10453SEric Joyner mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB; 175271d10453SEric Joyner if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) 175371d10453SEric Joyner mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING; 175471d10453SEric Joyner 175571d10453SEric Joyner ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg); 175671d10453SEric Joyner ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, 175771d10453SEric Joyner NULL); 175871d10453SEric Joyner 175971d10453SEric Joyner ice_free(hw, lldpmib); 176071d10453SEric Joyner 176171d10453SEric Joyner return ret; 176271d10453SEric Joyner } 176371d10453SEric Joyner 176471d10453SEric Joyner /** 176571d10453SEric Joyner * ice_aq_query_port_ets - query port ETS configuration 176671d10453SEric Joyner * @pi: port information structure 176771d10453SEric Joyner * @buf: pointer to buffer 176871d10453SEric Joyner * @buf_size: buffer size in bytes 176971d10453SEric Joyner * @cd: pointer to command details structure or NULL 177071d10453SEric Joyner * 177171d10453SEric Joyner * query current port ETS configuration 177271d10453SEric Joyner */ 1773*f2635e84SEric Joyner int 177471d10453SEric Joyner ice_aq_query_port_ets(struct ice_port_info *pi, 177571d10453SEric Joyner struct ice_aqc_port_ets_elem *buf, u16 buf_size, 177671d10453SEric Joyner struct ice_sq_cd *cd) 177771d10453SEric Joyner { 177871d10453SEric Joyner struct ice_aqc_query_port_ets *cmd; 177971d10453SEric Joyner struct ice_aq_desc desc; 1780*f2635e84SEric Joyner int status; 178171d10453SEric Joyner 178256429daeSEric Joyner if (!pi || !pi->root) 178371d10453SEric Joyner return ICE_ERR_PARAM; 178471d10453SEric Joyner cmd = &desc.params.port_ets; 178571d10453SEric Joyner ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets); 178671d10453SEric Joyner cmd->port_teid = pi->root->info.node_teid; 178771d10453SEric Joyner 178871d10453SEric Joyner status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd); 178971d10453SEric Joyner return status; 179071d10453SEric Joyner } 179171d10453SEric Joyner 179271d10453SEric Joyner /** 179371d10453SEric Joyner * ice_update_port_tc_tree_cfg - update TC tree configuration 179471d10453SEric Joyner * @pi: port information structure 179571d10453SEric Joyner * @buf: pointer to buffer 179671d10453SEric Joyner * 179771d10453SEric Joyner * update the SW DB with the new TC changes 179871d10453SEric Joyner */ 1799*f2635e84SEric Joyner int 180071d10453SEric Joyner ice_update_port_tc_tree_cfg(struct ice_port_info *pi, 180171d10453SEric Joyner struct ice_aqc_port_ets_elem *buf) 180271d10453SEric Joyner { 180371d10453SEric Joyner struct ice_sched_node *node, *tc_node; 18047d7af7f8SEric Joyner struct ice_aqc_txsched_elem_data elem; 180571d10453SEric Joyner u32 teid1, teid2; 1806*f2635e84SEric Joyner int status = 0; 180771d10453SEric Joyner u8 i, j; 180871d10453SEric Joyner 180971d10453SEric Joyner if (!pi) 181071d10453SEric Joyner return ICE_ERR_PARAM; 181171d10453SEric Joyner /* suspend the missing TC nodes */ 181271d10453SEric Joyner for (i = 0; i < pi->root->num_children; i++) { 181371d10453SEric Joyner teid1 = LE32_TO_CPU(pi->root->children[i]->info.node_teid); 181471d10453SEric Joyner ice_for_each_traffic_class(j) { 181571d10453SEric Joyner teid2 = LE32_TO_CPU(buf->tc_node_teid[j]); 181671d10453SEric Joyner if (teid1 == teid2) 181771d10453SEric Joyner break; 181871d10453SEric Joyner } 181971d10453SEric Joyner if (j < ICE_MAX_TRAFFIC_CLASS) 182071d10453SEric Joyner continue; 182171d10453SEric Joyner /* TC is missing */ 182271d10453SEric Joyner pi->root->children[i]->in_use = false; 182371d10453SEric Joyner } 182471d10453SEric Joyner /* add the new TC nodes */ 182571d10453SEric Joyner ice_for_each_traffic_class(j) { 182671d10453SEric Joyner teid2 = LE32_TO_CPU(buf->tc_node_teid[j]); 182771d10453SEric Joyner if (teid2 == ICE_INVAL_TEID) 182871d10453SEric Joyner continue; 182971d10453SEric Joyner /* Is it already present in the tree ? */ 183071d10453SEric Joyner for (i = 0; i < pi->root->num_children; i++) { 183171d10453SEric Joyner tc_node = pi->root->children[i]; 183271d10453SEric Joyner if (!tc_node) 183371d10453SEric Joyner continue; 183471d10453SEric Joyner teid1 = LE32_TO_CPU(tc_node->info.node_teid); 183571d10453SEric Joyner if (teid1 == teid2) { 183671d10453SEric Joyner tc_node->tc_num = j; 183771d10453SEric Joyner tc_node->in_use = true; 183871d10453SEric Joyner break; 183971d10453SEric Joyner } 184071d10453SEric Joyner } 184171d10453SEric Joyner if (i < pi->root->num_children) 184271d10453SEric Joyner continue; 184371d10453SEric Joyner /* new TC */ 184471d10453SEric Joyner status = ice_sched_query_elem(pi->hw, teid2, &elem); 184571d10453SEric Joyner if (!status) 18469c30461dSEric Joyner status = ice_sched_add_node(pi, 1, &elem, NULL); 184771d10453SEric Joyner if (status) 184871d10453SEric Joyner break; 184971d10453SEric Joyner /* update the TC number */ 185071d10453SEric Joyner node = ice_sched_find_node_by_teid(pi->root, teid2); 185171d10453SEric Joyner if (node) 185271d10453SEric Joyner node->tc_num = j; 185371d10453SEric Joyner } 185471d10453SEric Joyner return status; 185571d10453SEric Joyner } 185671d10453SEric Joyner 185771d10453SEric Joyner /** 185871d10453SEric Joyner * ice_query_port_ets - query port ETS configuration 185971d10453SEric Joyner * @pi: port information structure 186071d10453SEric Joyner * @buf: pointer to buffer 186171d10453SEric Joyner * @buf_size: buffer size in bytes 186271d10453SEric Joyner * @cd: pointer to command details structure or NULL 186371d10453SEric Joyner * 186471d10453SEric Joyner * query current port ETS configuration and update the 186571d10453SEric Joyner * SW DB with the TC changes 186671d10453SEric Joyner */ 1867*f2635e84SEric Joyner int 186871d10453SEric Joyner ice_query_port_ets(struct ice_port_info *pi, 186971d10453SEric Joyner struct ice_aqc_port_ets_elem *buf, u16 buf_size, 187071d10453SEric Joyner struct ice_sq_cd *cd) 187171d10453SEric Joyner { 1872*f2635e84SEric Joyner int status; 187371d10453SEric Joyner 187471d10453SEric Joyner ice_acquire_lock(&pi->sched_lock); 187571d10453SEric Joyner status = ice_aq_query_port_ets(pi, buf, buf_size, cd); 187671d10453SEric Joyner if (!status) 187771d10453SEric Joyner status = ice_update_port_tc_tree_cfg(pi, buf); 187871d10453SEric Joyner ice_release_lock(&pi->sched_lock); 187971d10453SEric Joyner return status; 188071d10453SEric Joyner } 1881