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