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