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