brintos

brintos / linux-shallow public Read only

0
0
Text · 42.5 KiB · 74418c4 Raw
1642 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2019, Intel Corporation. */3 4#include "ice_common.h"5#include "ice_sched.h"6#include "ice_dcb.h"7 8/**9 * ice_aq_get_lldp_mib10 * @hw: pointer to the HW struct11 * @bridge_type: type of bridge requested12 * @mib_type: Local, Remote or both Local and Remote MIBs13 * @buf: pointer to the caller-supplied buffer to store the MIB block14 * @buf_size: size of the buffer (in bytes)15 * @local_len: length of the returned Local LLDP MIB16 * @remote_len: length of the returned Remote LLDP MIB17 * @cd: pointer to command details structure or NULL18 *19 * Requests the complete LLDP MIB (entire packet). (0x0A00)20 */21static int22ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf,23		    u16 buf_size, u16 *local_len, u16 *remote_len,24		    struct ice_sq_cd *cd)25{26	struct ice_aqc_lldp_get_mib *cmd;27	struct ice_aq_desc desc;28	int status;29 30	cmd = &desc.params.lldp_get_mib;31 32	if (buf_size == 0 || !buf)33		return -EINVAL;34 35	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_get_mib);36 37	cmd->type = mib_type & ICE_AQ_LLDP_MIB_TYPE_M;38	cmd->type |= FIELD_PREP(ICE_AQ_LLDP_BRID_TYPE_M, bridge_type);39 40	desc.datalen = cpu_to_le16(buf_size);41 42	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);43	if (!status) {44		if (local_len)45			*local_len = le16_to_cpu(cmd->local_len);46		if (remote_len)47			*remote_len = le16_to_cpu(cmd->remote_len);48	}49 50	return status;51}52 53/**54 * ice_aq_cfg_lldp_mib_change55 * @hw: pointer to the HW struct56 * @ena_update: Enable or Disable event posting57 * @cd: pointer to command details structure or NULL58 *59 * Enable or Disable posting of an event on ARQ when LLDP MIB60 * associated with the interface changes (0x0A01)61 */62static int63ice_aq_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_update,64			   struct ice_sq_cd *cd)65{66	struct ice_aqc_lldp_set_mib_change *cmd;67	struct ice_aq_desc desc;68 69	cmd = &desc.params.lldp_set_event;70 71	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_mib_change);72 73	if (!ena_update)74		cmd->command |= ICE_AQ_LLDP_MIB_UPDATE_DIS;75	else76		cmd->command |= FIELD_PREP(ICE_AQ_LLDP_MIB_PENDING_M,77					   ICE_AQ_LLDP_MIB_PENDING_ENABLE);78 79	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);80}81 82/**83 * ice_aq_stop_lldp84 * @hw: pointer to the HW struct85 * @shutdown_lldp_agent: True if LLDP Agent needs to be Shutdown86 *			 False if LLDP Agent needs to be Stopped87 * @persist: True if Stop/Shutdown of LLDP Agent needs to be persistent across88 *	     reboots89 * @cd: pointer to command details structure or NULL90 *91 * Stop or Shutdown the embedded LLDP Agent (0x0A05)92 */93int94ice_aq_stop_lldp(struct ice_hw *hw, bool shutdown_lldp_agent, bool persist,95		 struct ice_sq_cd *cd)96{97	struct ice_aqc_lldp_stop *cmd;98	struct ice_aq_desc desc;99 100	cmd = &desc.params.lldp_stop;101 102	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_stop);103 104	if (shutdown_lldp_agent)105		cmd->command |= ICE_AQ_LLDP_AGENT_SHUTDOWN;106 107	if (persist)108		cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_DIS;109 110	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);111}112 113/**114 * ice_aq_start_lldp115 * @hw: pointer to the HW struct116 * @persist: True if Start of LLDP Agent needs to be persistent across reboots117 * @cd: pointer to command details structure or NULL118 *119 * Start the embedded LLDP Agent on all ports. (0x0A06)120 */121int ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd)122{123	struct ice_aqc_lldp_start *cmd;124	struct ice_aq_desc desc;125 126	cmd = &desc.params.lldp_start;127 128	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start);129 130	cmd->command = ICE_AQ_LLDP_AGENT_START;131 132	if (persist)133		cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_ENA;134 135	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);136}137 138/**139 * ice_get_dcbx_status140 * @hw: pointer to the HW struct141 *142 * Get the DCBX status from the Firmware143 */144static u8 ice_get_dcbx_status(struct ice_hw *hw)145{146	u32 reg;147 148	reg = rd32(hw, PRTDCB_GENS);149	return FIELD_GET(PRTDCB_GENS_DCBX_STATUS_M, reg);150}151 152/**153 * ice_parse_ieee_ets_common_tlv154 * @buf: Data buffer to be parsed for ETS CFG/REC data155 * @ets_cfg: Container to store parsed data156 *157 * Parses the common data of IEEE 802.1Qaz ETS CFG/REC TLV158 */159static void160ice_parse_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)161{162	u8 offset = 0;163	int i;164 165	/* Priority Assignment Table (4 octets)166	 * Octets:|    1    |    2    |    3    |    4    |167	 *        -----------------------------------------168	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|169	 *        -----------------------------------------170	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|171	 *        -----------------------------------------172	 */173	for (i = 0; i < 4; i++) {174		ets_cfg->prio_table[i * 2] =175			FIELD_GET(ICE_IEEE_ETS_PRIO_1_M, buf[offset]);176		ets_cfg->prio_table[i * 2 + 1] =177			FIELD_GET(ICE_IEEE_ETS_PRIO_0_M, buf[offset]);178		offset++;179	}180 181	/* TC Bandwidth Table (8 octets)182	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |183	 *        ---------------------------------184	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|185	 *        ---------------------------------186	 *187	 * TSA Assignment Table (8 octets)188	 * Octets:| 9 | 10| 11| 12| 13| 14| 15| 16|189	 *        ---------------------------------190	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|191	 *        ---------------------------------192	 */193	ice_for_each_traffic_class(i) {194		ets_cfg->tcbwtable[i] = buf[offset];195		ets_cfg->tsatable[i] = buf[ICE_MAX_TRAFFIC_CLASS + offset++];196	}197}198 199/**200 * ice_parse_ieee_etscfg_tlv201 * @tlv: IEEE 802.1Qaz ETS CFG TLV202 * @dcbcfg: Local store to update ETS CFG data203 *204 * Parses IEEE 802.1Qaz ETS CFG TLV205 */206static void207ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv *tlv,208			  struct ice_dcbx_cfg *dcbcfg)209{210	struct ice_dcb_ets_cfg *etscfg;211	u8 *buf = tlv->tlvinfo;212 213	/* First Octet post subtype214	 * --------------------------215	 * |will-|CBS  | Re-  | Max |216	 * |ing  |     |served| TCs |217	 * --------------------------218	 * |1bit | 1bit|3 bits|3bits|219	 */220	etscfg = &dcbcfg->etscfg;221	etscfg->willing = FIELD_GET(ICE_IEEE_ETS_WILLING_M, buf[0]);222	etscfg->cbs = FIELD_GET(ICE_IEEE_ETS_CBS_M, buf[0]);223	etscfg->maxtcs = FIELD_GET(ICE_IEEE_ETS_MAXTC_M, buf[0]);224 225	/* Begin parsing at Priority Assignment Table (offset 1 in buf) */226	ice_parse_ieee_ets_common_tlv(&buf[1], etscfg);227}228 229/**230 * ice_parse_ieee_etsrec_tlv231 * @tlv: IEEE 802.1Qaz ETS REC TLV232 * @dcbcfg: Local store to update ETS REC data233 *234 * Parses IEEE 802.1Qaz ETS REC TLV235 */236static void237ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,238			  struct ice_dcbx_cfg *dcbcfg)239{240	u8 *buf = tlv->tlvinfo;241 242	/* Begin parsing at Priority Assignment Table (offset 1 in buf) */243	ice_parse_ieee_ets_common_tlv(&buf[1], &dcbcfg->etsrec);244}245 246/**247 * ice_parse_ieee_pfccfg_tlv248 * @tlv: IEEE 802.1Qaz PFC CFG TLV249 * @dcbcfg: Local store to update PFC CFG data250 *251 * Parses IEEE 802.1Qaz PFC CFG TLV252 */253static void254ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv *tlv,255			  struct ice_dcbx_cfg *dcbcfg)256{257	u8 *buf = tlv->tlvinfo;258 259	/* ----------------------------------------260	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |261	 * |ing  |     |served| cap |              |262	 * -----------------------------------------263	 * |1bit | 1bit|2 bits|4bits| 1 octet      |264	 */265	dcbcfg->pfc.willing = FIELD_GET(ICE_IEEE_PFC_WILLING_M, buf[0]);266	dcbcfg->pfc.mbc = FIELD_GET(ICE_IEEE_PFC_MBC_M, buf[0]);267	dcbcfg->pfc.pfccap = FIELD_GET(ICE_IEEE_PFC_CAP_M, buf[0]);268	dcbcfg->pfc.pfcena = buf[1];269}270 271/**272 * ice_parse_ieee_app_tlv273 * @tlv: IEEE 802.1Qaz APP TLV274 * @dcbcfg: Local store to update APP PRIO data275 *276 * Parses IEEE 802.1Qaz APP PRIO TLV277 */278static void279ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv *tlv,280		       struct ice_dcbx_cfg *dcbcfg)281{282	u16 offset = 0;283	u16 typelen;284	int i = 0;285	u16 len;286	u8 *buf;287 288	typelen = ntohs(tlv->typelen);289	len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);290	buf = tlv->tlvinfo;291 292	/* Removing sizeof(ouisubtype) and reserved byte from len.293	 * Remaining len div 3 is number of APP TLVs.294	 */295	len -= (sizeof(tlv->ouisubtype) + 1);296 297	/* Move offset to App Priority Table */298	offset++;299 300	/* Application Priority Table (3 octets)301	 * Octets:|         1          |    2    |    3    |302	 *        -----------------------------------------303	 *        |Priority|Rsrvd| Sel |    Protocol ID    |304	 *        -----------------------------------------305	 *   Bits:|23    21|20 19|18 16|15                0|306	 *        -----------------------------------------307	 */308	while (offset < len) {309		dcbcfg->app[i].priority = FIELD_GET(ICE_IEEE_APP_PRIO_M,310						    buf[offset]);311		dcbcfg->app[i].selector = FIELD_GET(ICE_IEEE_APP_SEL_M,312						    buf[offset]);313		dcbcfg->app[i].prot_id = (buf[offset + 1] << 0x8) |314			buf[offset + 2];315		/* Move to next app */316		offset += 3;317		i++;318		if (i >= ICE_DCBX_MAX_APPS)319			break;320	}321 322	dcbcfg->numapps = i;323}324 325/**326 * ice_parse_ieee_tlv327 * @tlv: IEEE 802.1Qaz TLV328 * @dcbcfg: Local store to update ETS REC data329 *330 * Get the TLV subtype and send it to parsing function331 * based on the subtype value332 */333static void334ice_parse_ieee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)335{336	u32 ouisubtype;337	u8 subtype;338 339	ouisubtype = ntohl(tlv->ouisubtype);340	subtype = FIELD_GET(ICE_LLDP_TLV_SUBTYPE_M, ouisubtype);341	switch (subtype) {342	case ICE_IEEE_SUBTYPE_ETS_CFG:343		ice_parse_ieee_etscfg_tlv(tlv, dcbcfg);344		break;345	case ICE_IEEE_SUBTYPE_ETS_REC:346		ice_parse_ieee_etsrec_tlv(tlv, dcbcfg);347		break;348	case ICE_IEEE_SUBTYPE_PFC_CFG:349		ice_parse_ieee_pfccfg_tlv(tlv, dcbcfg);350		break;351	case ICE_IEEE_SUBTYPE_APP_PRI:352		ice_parse_ieee_app_tlv(tlv, dcbcfg);353		break;354	default:355		break;356	}357}358 359/**360 * ice_parse_cee_pgcfg_tlv361 * @tlv: CEE DCBX PG CFG TLV362 * @dcbcfg: Local store to update ETS CFG data363 *364 * Parses CEE DCBX PG CFG TLV365 */366static void367ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv *tlv,368			struct ice_dcbx_cfg *dcbcfg)369{370	struct ice_dcb_ets_cfg *etscfg;371	u8 *buf = tlv->tlvinfo;372	u16 offset = 0;373	int i;374 375	etscfg = &dcbcfg->etscfg;376 377	if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)378		etscfg->willing = 1;379 380	etscfg->cbs = 0;381	/* Priority Group Table (4 octets)382	 * Octets:|    1    |    2    |    3    |    4    |383	 *        -----------------------------------------384	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|385	 *        -----------------------------------------386	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|387	 *        -----------------------------------------388	 */389	for (i = 0; i < 4; i++) {390		etscfg->prio_table[i * 2] =391			FIELD_GET(ICE_CEE_PGID_PRIO_1_M, buf[offset]);392		etscfg->prio_table[i * 2 + 1] =393			FIELD_GET(ICE_CEE_PGID_PRIO_0_M, buf[offset]);394		offset++;395	}396 397	/* PG Percentage Table (8 octets)398	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |399	 *        ---------------------------------400	 *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|401	 *        ---------------------------------402	 */403	ice_for_each_traffic_class(i) {404		etscfg->tcbwtable[i] = buf[offset++];405 406		if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT)407			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;408		else409			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;410	}411 412	/* Number of TCs supported (1 octet) */413	etscfg->maxtcs = buf[offset];414}415 416/**417 * ice_parse_cee_pfccfg_tlv418 * @tlv: CEE DCBX PFC CFG TLV419 * @dcbcfg: Local store to update PFC CFG data420 *421 * Parses CEE DCBX PFC CFG TLV422 */423static void424ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv,425			 struct ice_dcbx_cfg *dcbcfg)426{427	u8 *buf = tlv->tlvinfo;428 429	if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)430		dcbcfg->pfc.willing = 1;431 432	/* ------------------------433	 * | PFC Enable | PFC TCs |434	 * ------------------------435	 * | 1 octet    | 1 octet |436	 */437	dcbcfg->pfc.pfcena = buf[0];438	dcbcfg->pfc.pfccap = buf[1];439}440 441/**442 * ice_parse_cee_app_tlv443 * @tlv: CEE DCBX APP TLV444 * @dcbcfg: Local store to update APP PRIO data445 *446 * Parses CEE DCBX APP PRIO TLV447 */448static void449ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)450{451	u16 len, typelen, offset = 0;452	struct ice_cee_app_prio *app;453	u8 i;454 455	typelen = ntohs(tlv->hdr.typelen);456	len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);457 458	dcbcfg->numapps = len / sizeof(*app);459	if (!dcbcfg->numapps)460		return;461	if (dcbcfg->numapps > ICE_DCBX_MAX_APPS)462		dcbcfg->numapps = ICE_DCBX_MAX_APPS;463 464	for (i = 0; i < dcbcfg->numapps; i++) {465		u8 up, selector;466 467		app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset);468		for (up = 0; up < ICE_MAX_USER_PRIORITY; up++)469			if (app->prio_map & BIT(up))470				break;471 472		dcbcfg->app[i].priority = up;473 474		/* Get Selector from lower 2 bits, and convert to IEEE */475		selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M);476		switch (selector) {477		case ICE_CEE_APP_SEL_ETHTYPE:478			dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE;479			break;480		case ICE_CEE_APP_SEL_TCPIP:481			dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP;482			break;483		default:484			/* Keep selector as it is for unknown types */485			dcbcfg->app[i].selector = selector;486		}487 488		dcbcfg->app[i].prot_id = ntohs(app->protocol);489		/* Move to next app */490		offset += sizeof(*app);491	}492}493 494/**495 * ice_parse_cee_tlv496 * @tlv: CEE DCBX TLV497 * @dcbcfg: Local store to update DCBX config data498 *499 * Get the TLV subtype and send it to parsing function500 * based on the subtype value501 */502static void503ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)504{505	struct ice_cee_feat_tlv *sub_tlv;506	u8 subtype, feat_tlv_count = 0;507	u16 len, tlvlen, typelen;508	u32 ouisubtype;509 510	ouisubtype = ntohl(tlv->ouisubtype);511	subtype = FIELD_GET(ICE_LLDP_TLV_SUBTYPE_M, ouisubtype);512	/* Return if not CEE DCBX */513	if (subtype != ICE_CEE_DCBX_TYPE)514		return;515 516	typelen = ntohs(tlv->typelen);517	tlvlen = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);518	len = sizeof(tlv->typelen) + sizeof(ouisubtype) +519		sizeof(struct ice_cee_ctrl_tlv);520	/* Return if no CEE DCBX Feature TLVs */521	if (tlvlen <= len)522		return;523 524	sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len);525	while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) {526		u16 sublen;527 528		typelen = ntohs(sub_tlv->hdr.typelen);529		sublen = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);530		subtype = FIELD_GET(ICE_LLDP_TLV_TYPE_M, typelen);531		switch (subtype) {532		case ICE_CEE_SUBTYPE_PG_CFG:533			ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);534			break;535		case ICE_CEE_SUBTYPE_PFC_CFG:536			ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);537			break;538		case ICE_CEE_SUBTYPE_APP_PRI:539			ice_parse_cee_app_tlv(sub_tlv, dcbcfg);540			break;541		default:542			return;	/* Invalid Sub-type return */543		}544		feat_tlv_count++;545		/* Move to next sub TLV */546		sub_tlv = (struct ice_cee_feat_tlv *)547			  ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) +548			   sublen);549	}550}551 552/**553 * ice_parse_org_tlv554 * @tlv: Organization specific TLV555 * @dcbcfg: Local store to update ETS REC data556 *557 * Currently IEEE 802.1Qaz and CEE DCBX TLV are supported, others558 * will be returned559 */560static void561ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)562{563	u32 ouisubtype;564	u32 oui;565 566	ouisubtype = ntohl(tlv->ouisubtype);567	oui = FIELD_GET(ICE_LLDP_TLV_OUI_M, ouisubtype);568	switch (oui) {569	case ICE_IEEE_8021QAZ_OUI:570		ice_parse_ieee_tlv(tlv, dcbcfg);571		break;572	case ICE_CEE_DCBX_OUI:573		ice_parse_cee_tlv(tlv, dcbcfg);574		break;575	default:576		break; /* Other OUIs not supported */577	}578}579 580/**581 * ice_lldp_to_dcb_cfg582 * @lldpmib: LLDPDU to be parsed583 * @dcbcfg: store for LLDPDU data584 *585 * Parse DCB configuration from the LLDPDU586 */587static int ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)588{589	struct ice_lldp_org_tlv *tlv;590	u16 offset = 0;591	int ret = 0;592	u16 typelen;593	u16 type;594	u16 len;595 596	if (!lldpmib || !dcbcfg)597		return -EINVAL;598 599	/* set to the start of LLDPDU */600	lldpmib += ETH_HLEN;601	tlv = (struct ice_lldp_org_tlv *)lldpmib;602	while (1) {603		typelen = ntohs(tlv->typelen);604		type = FIELD_GET(ICE_LLDP_TLV_TYPE_M, typelen);605		len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);606		offset += sizeof(typelen) + len;607 608		/* END TLV or beyond LLDPDU size */609		if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE)610			break;611 612		switch (type) {613		case ICE_TLV_TYPE_ORG:614			ice_parse_org_tlv(tlv, dcbcfg);615			break;616		default:617			break;618		}619 620		/* Move to next TLV */621		tlv = (struct ice_lldp_org_tlv *)622		      ((char *)tlv + sizeof(tlv->typelen) + len);623	}624 625	return ret;626}627 628/**629 * ice_aq_get_dcb_cfg630 * @hw: pointer to the HW struct631 * @mib_type: MIB type for the query632 * @bridgetype: bridge type for the query (remote)633 * @dcbcfg: store for LLDPDU data634 *635 * Query DCB configuration from the firmware636 */637int638ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,639		   struct ice_dcbx_cfg *dcbcfg)640{641	u8 *lldpmib;642	int ret;643 644	/* Allocate the LLDPDU */645	lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);646	if (!lldpmib)647		return -ENOMEM;648 649	ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib,650				  ICE_LLDPDU_SIZE, NULL, NULL, NULL);651 652	if (!ret)653		/* Parse LLDP MIB to get DCB configuration */654		ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg);655 656	devm_kfree(ice_hw_to_dev(hw), lldpmib);657 658	return ret;659}660 661/**662 * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW663 * @hw: pointer to the HW struct664 * @start_dcbx_agent: True if DCBX Agent needs to be started665 *		      False if DCBX Agent needs to be stopped666 * @dcbx_agent_status: FW indicates back the DCBX agent status667 *		       True if DCBX Agent is active668 *		       False if DCBX Agent is stopped669 * @cd: pointer to command details structure or NULL670 *671 * Start/Stop the embedded dcbx Agent. In case that this wrapper function672 * returns 0, caller will need to check if FW returns back the same673 * value as stated in dcbx_agent_status, and react accordingly. (0x0A09)674 */675int676ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent,677		       bool *dcbx_agent_status, struct ice_sq_cd *cd)678{679	struct ice_aqc_lldp_stop_start_specific_agent *cmd;680	struct ice_aq_desc desc;681	u16 opcode;682	int status;683 684	cmd = &desc.params.lldp_agent_ctrl;685 686	opcode = ice_aqc_opc_lldp_stop_start_specific_agent;687 688	ice_fill_dflt_direct_cmd_desc(&desc, opcode);689 690	if (start_dcbx_agent)691		cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX;692 693	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);694 695	*dcbx_agent_status = false;696 697	if (!status &&698	    cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX)699		*dcbx_agent_status = true;700 701	return status;702}703 704/**705 * ice_aq_get_cee_dcb_cfg706 * @hw: pointer to the HW struct707 * @buff: response buffer that stores CEE operational configuration708 * @cd: pointer to command details structure or NULL709 *710 * Get CEE DCBX mode operational configuration from firmware (0x0A07)711 */712static int713ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,714		       struct ice_aqc_get_cee_dcb_cfg_resp *buff,715		       struct ice_sq_cd *cd)716{717	struct ice_aq_desc desc;718 719	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg);720 721	return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd);722}723 724/**725 * ice_aq_set_pfc_mode - Set PFC mode726 * @hw: pointer to the HW struct727 * @pfc_mode: value of PFC mode to set728 * @cd: pointer to command details structure or NULL729 *730 * This AQ call configures the PFC mode to DSCP-based PFC mode or731 * VLAN-based PFC (0x0303)732 */733int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd)734{735	struct ice_aqc_set_query_pfc_mode *cmd;736	struct ice_aq_desc desc;737	int status;738 739	if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC)740		return -EINVAL;741 742	cmd = &desc.params.set_query_pfc_mode;743 744	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode);745 746	cmd->pfc_mode = pfc_mode;747 748	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);749	if (status)750		return status;751 752	/* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is753	 * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has754	 * been executed, check if cmd->pfc_mode is what was requested. If not,755	 * return an error.756	 */757	if (cmd->pfc_mode != pfc_mode)758		return -EOPNOTSUPP;759 760	return 0;761}762 763/**764 * ice_cee_to_dcb_cfg765 * @cee_cfg: pointer to CEE configuration struct766 * @pi: port information structure767 *768 * Convert CEE configuration from firmware to DCB configuration769 */770static void771ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,772		   struct ice_port_info *pi)773{774	u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);775	u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift, j;776	u8 i, err, sync, oper, app_index, ice_app_sel_type;777	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);778	u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift;779	struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg;780	u16 ice_app_prot_id_type;781 782	dcbcfg = &pi->qos_cfg.local_dcbx_cfg;783	dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE;784	dcbcfg->tlv_status = tlv_status;785 786	/* CEE PG data */787	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;788 789	/* Note that the FW creates the oper_prio_tc nibbles reversed790	 * from those in the CEE Priority Group sub-TLV.791	 */792	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {793		dcbcfg->etscfg.prio_table[i * 2] =794			FIELD_GET(ICE_CEE_PGID_PRIO_0_M,795				  cee_cfg->oper_prio_tc[i]);796		dcbcfg->etscfg.prio_table[i * 2 + 1] =797			FIELD_GET(ICE_CEE_PGID_PRIO_1_M,798				  cee_cfg->oper_prio_tc[i]);799	}800 801	ice_for_each_traffic_class(i) {802		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];803 804		if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) {805			/* Map it to next empty TC */806			dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1;807			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;808		} else {809			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;810		}811	}812 813	/* CEE PFC data */814	dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en;815	dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS;816 817	/* CEE APP TLV data */818	if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)819		cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg;820	else821		cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg;822 823	app_index = 0;824	for (i = 0; i < 3; i++) {825		if (i == 0) {826			/* FCoE APP */827			ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M;828			ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S;829			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M;830			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S;831			ice_app_sel_type = ICE_APP_SEL_ETHTYPE;832			ice_app_prot_id_type = ETH_P_FCOE;833		} else if (i == 1) {834			/* iSCSI APP */835			ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M;836			ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S;837			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M;838			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S;839			ice_app_sel_type = ICE_APP_SEL_TCPIP;840			ice_app_prot_id_type = ISCSI_LISTEN_PORT;841 842			for (j = 0; j < cmp_dcbcfg->numapps; j++) {843				u16 prot_id = cmp_dcbcfg->app[j].prot_id;844				u8 sel = cmp_dcbcfg->app[j].selector;845 846				if  (sel == ICE_APP_SEL_TCPIP &&847				     (prot_id == ISCSI_LISTEN_PORT ||848				      prot_id == ICE_APP_PROT_ID_ISCSI_860)) {849					ice_app_prot_id_type = prot_id;850					break;851				}852			}853		} else {854			/* FIP APP */855			ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M;856			ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S;857			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M;858			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S;859			ice_app_sel_type = ICE_APP_SEL_ETHTYPE;860			ice_app_prot_id_type = ETH_P_FIP;861		}862 863		status = (tlv_status & ice_aqc_cee_status_mask) >>864			 ice_aqc_cee_status_shift;865		err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0;866		sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0;867		oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0;868		/* Add FCoE/iSCSI/FIP APP if Error is False and869		 * Oper/Sync is True870		 */871		if (!err && sync && oper) {872			dcbcfg->app[app_index].priority =873				(app_prio & ice_aqc_cee_app_mask) >>874				ice_aqc_cee_app_shift;875			dcbcfg->app[app_index].selector = ice_app_sel_type;876			dcbcfg->app[app_index].prot_id = ice_app_prot_id_type;877			app_index++;878		}879	}880 881	dcbcfg->numapps = app_index;882}883 884/**885 * ice_get_ieee_or_cee_dcb_cfg886 * @pi: port information structure887 * @dcbx_mode: mode of DCBX (IEEE or CEE)888 *889 * Get IEEE or CEE mode DCB configuration from the Firmware890 */891static int ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode)892{893	struct ice_dcbx_cfg *dcbx_cfg = NULL;894	int ret;895 896	if (!pi)897		return -EINVAL;898 899	if (dcbx_mode == ICE_DCBX_MODE_IEEE)900		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;901	else if (dcbx_mode == ICE_DCBX_MODE_CEE)902		dcbx_cfg = &pi->qos_cfg.desired_dcbx_cfg;903 904	/* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE905	 * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE906	 */907	ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL,908				 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);909	if (ret)910		goto out;911 912	/* Get Remote DCB Config */913	dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg;914	ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,915				 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);916	/* Don't treat ENOENT as an error for Remote MIBs */917	if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)918		ret = 0;919 920out:921	return ret;922}923 924/**925 * ice_get_dcb_cfg926 * @pi: port information structure927 *928 * Get DCB configuration from the Firmware929 */930int ice_get_dcb_cfg(struct ice_port_info *pi)931{932	struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg;933	struct ice_dcbx_cfg *dcbx_cfg;934	int ret;935 936	if (!pi)937		return -EINVAL;938 939	ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL);940	if (!ret) {941		/* CEE mode */942		ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE);943		ice_cee_to_dcb_cfg(&cee_cfg, pi);944	} else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) {945		/* CEE mode not enabled try querying IEEE data */946		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;947		dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE;948		ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE);949	}950 951	return ret;952}953 954/**955 * ice_get_dcb_cfg_from_mib_change956 * @pi: port information structure957 * @event: pointer to the admin queue receive event958 *959 * Set DCB configuration from received MIB Change event960 */961void ice_get_dcb_cfg_from_mib_change(struct ice_port_info *pi,962				     struct ice_rq_event_info *event)963{964	struct ice_dcbx_cfg *dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;965	struct ice_aqc_lldp_get_mib *mib;966	u8 change_type, dcbx_mode;967 968	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;969 970	change_type = FIELD_GET(ICE_AQ_LLDP_MIB_TYPE_M, mib->type);971	if (change_type == ICE_AQ_LLDP_MIB_REMOTE)972		dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg;973 974	dcbx_mode = FIELD_GET(ICE_AQ_LLDP_DCBX_M, mib->type);975 976	switch (dcbx_mode) {977	case ICE_AQ_LLDP_DCBX_IEEE:978		dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE;979		ice_lldp_to_dcb_cfg(event->msg_buf, dcbx_cfg);980		break;981 982	case ICE_AQ_LLDP_DCBX_CEE:983		pi->qos_cfg.desired_dcbx_cfg = pi->qos_cfg.local_dcbx_cfg;984		ice_cee_to_dcb_cfg((struct ice_aqc_get_cee_dcb_cfg_resp *)985				   event->msg_buf, pi);986		break;987	}988}989 990/**991 * ice_init_dcb992 * @hw: pointer to the HW struct993 * @enable_mib_change: enable MIB change event994 *995 * Update DCB configuration from the Firmware996 */997int ice_init_dcb(struct ice_hw *hw, bool enable_mib_change)998{999	struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;1000	int ret = 0;1001 1002	if (!hw->func_caps.common_cap.dcb)1003		return -EOPNOTSUPP;1004 1005	qos_cfg->is_sw_lldp = true;1006 1007	/* Get DCBX status */1008	qos_cfg->dcbx_status = ice_get_dcbx_status(hw);1009 1010	if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DONE ||1011	    qos_cfg->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS ||1012	    qos_cfg->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) {1013		/* Get current DCBX configuration */1014		ret = ice_get_dcb_cfg(hw->port_info);1015		if (ret)1016			return ret;1017		qos_cfg->is_sw_lldp = false;1018	} else if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) {1019		return -EBUSY;1020	}1021 1022	/* Configure the LLDP MIB change event */1023	if (enable_mib_change) {1024		ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL);1025		if (ret)1026			qos_cfg->is_sw_lldp = true;1027	}1028 1029	return ret;1030}1031 1032/**1033 * ice_cfg_lldp_mib_change1034 * @hw: pointer to the HW struct1035 * @ena_mib: enable/disable MIB change event1036 *1037 * Configure (disable/enable) MIB1038 */1039int ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib)1040{1041	struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;1042	int ret;1043 1044	if (!hw->func_caps.common_cap.dcb)1045		return -EOPNOTSUPP;1046 1047	/* Get DCBX status */1048	qos_cfg->dcbx_status = ice_get_dcbx_status(hw);1049 1050	if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS)1051		return -EBUSY;1052 1053	ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL);1054	if (!ret)1055		qos_cfg->is_sw_lldp = !ena_mib;1056 1057	return ret;1058}1059 1060/**1061 * ice_add_ieee_ets_common_tlv1062 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data1063 * @ets_cfg: Container for ice_dcb_ets_cfg data1064 *1065 * Populate the TLV buffer with ice_dcb_ets_cfg data1066 */1067static void1068ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)1069{1070	u8 priority0, priority1;1071	u8 offset = 0;1072	int i;1073 1074	/* Priority Assignment Table (4 octets)1075	 * Octets:|    1    |    2    |    3    |    4    |1076	 *        -----------------------------------------1077	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|1078	 *        -----------------------------------------1079	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|1080	 *        -----------------------------------------1081	 */1082	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {1083		priority0 = ets_cfg->prio_table[i * 2] & 0xF;1084		priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF;1085		buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1;1086		offset++;1087	}1088 1089	/* TC Bandwidth Table (8 octets)1090	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |1091	 *        ---------------------------------1092	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1093	 *        ---------------------------------1094	 *1095	 * TSA Assignment Table (8 octets)1096	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |1097	 *        ---------------------------------1098	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1099	 *        ---------------------------------1100	 */1101	ice_for_each_traffic_class(i) {1102		buf[offset] = ets_cfg->tcbwtable[i];1103		buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i];1104		offset++;1105	}1106}1107 1108/**1109 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format1110 * @tlv: Fill the ETS config data in IEEE format1111 * @dcbcfg: Local store which holds the DCB Config1112 *1113 * Prepare IEEE 802.1Qaz ETS CFG TLV1114 */1115static void1116ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)1117{1118	struct ice_dcb_ets_cfg *etscfg;1119	u8 *buf = tlv->tlvinfo;1120	u8 maxtcwilling = 0;1121	u32 ouisubtype;1122	u16 typelen;1123 1124	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1125		   ICE_IEEE_ETS_TLV_LEN);1126	tlv->typelen = htons(typelen);1127 1128	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |1129		      ICE_IEEE_SUBTYPE_ETS_CFG);1130	tlv->ouisubtype = htonl(ouisubtype);1131 1132	/* First Octet post subtype1133	 * --------------------------1134	 * |will-|CBS  | Re-  | Max |1135	 * |ing  |     |served| TCs |1136	 * --------------------------1137	 * |1bit | 1bit|3 bits|3bits|1138	 */1139	etscfg = &dcbcfg->etscfg;1140	if (etscfg->willing)1141		maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S);1142	maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;1143	buf[0] = maxtcwilling;1144 1145	/* Begin adding at Priority Assignment Table (offset 1 in buf) */1146	ice_add_ieee_ets_common_tlv(&buf[1], etscfg);1147}1148 1149/**1150 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format1151 * @tlv: Fill ETS Recommended TLV in IEEE format1152 * @dcbcfg: Local store which holds the DCB Config1153 *1154 * Prepare IEEE 802.1Qaz ETS REC TLV1155 */1156static void1157ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,1158			struct ice_dcbx_cfg *dcbcfg)1159{1160	struct ice_dcb_ets_cfg *etsrec;1161	u8 *buf = tlv->tlvinfo;1162	u32 ouisubtype;1163	u16 typelen;1164 1165	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1166		   ICE_IEEE_ETS_TLV_LEN);1167	tlv->typelen = htons(typelen);1168 1169	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |1170		      ICE_IEEE_SUBTYPE_ETS_REC);1171	tlv->ouisubtype = htonl(ouisubtype);1172 1173	etsrec = &dcbcfg->etsrec;1174 1175	/* First Octet is reserved */1176	/* Begin adding at Priority Assignment Table (offset 1 in buf) */1177	ice_add_ieee_ets_common_tlv(&buf[1], etsrec);1178}1179 1180/**1181 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format1182 * @tlv: Fill PFC TLV in IEEE format1183 * @dcbcfg: Local store which holds the PFC CFG data1184 *1185 * Prepare IEEE 802.1Qaz PFC CFG TLV1186 */1187static void1188ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)1189{1190	u8 *buf = tlv->tlvinfo;1191	u32 ouisubtype;1192	u16 typelen;1193 1194	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1195		   ICE_IEEE_PFC_TLV_LEN);1196	tlv->typelen = htons(typelen);1197 1198	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |1199		      ICE_IEEE_SUBTYPE_PFC_CFG);1200	tlv->ouisubtype = htonl(ouisubtype);1201 1202	/* ----------------------------------------1203	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |1204	 * |ing  |     |served| cap |              |1205	 * -----------------------------------------1206	 * |1bit | 1bit|2 bits|4bits| 1 octet      |1207	 */1208	if (dcbcfg->pfc.willing)1209		buf[0] = BIT(ICE_IEEE_PFC_WILLING_S);1210 1211	if (dcbcfg->pfc.mbc)1212		buf[0] |= BIT(ICE_IEEE_PFC_MBC_S);1213 1214	buf[0] |= dcbcfg->pfc.pfccap & 0xF;1215	buf[1] = dcbcfg->pfc.pfcena;1216}1217 1218/**1219 * ice_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format1220 * @tlv: Fill APP TLV in IEEE format1221 * @dcbcfg: Local store which holds the APP CFG data1222 *1223 * Prepare IEEE 802.1Qaz APP CFG TLV1224 */1225static void1226ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,1227			 struct ice_dcbx_cfg *dcbcfg)1228{1229	u16 typelen, len, offset = 0;1230	u8 priority, selector, i = 0;1231	u8 *buf = tlv->tlvinfo;1232	u32 ouisubtype;1233 1234	/* No APP TLVs then just return */1235	if (dcbcfg->numapps == 0)1236		return;1237	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |1238		      ICE_IEEE_SUBTYPE_APP_PRI);1239	tlv->ouisubtype = htonl(ouisubtype);1240 1241	/* Move offset to App Priority Table */1242	offset++;1243	/* Application Priority Table (3 octets)1244	 * Octets:|         1          |    2    |    3    |1245	 *        -----------------------------------------1246	 *        |Priority|Rsrvd| Sel |    Protocol ID    |1247	 *        -----------------------------------------1248	 *   Bits:|23    21|20 19|18 16|15                0|1249	 *        -----------------------------------------1250	 */1251	while (i < dcbcfg->numapps) {1252		priority = dcbcfg->app[i].priority & 0x7;1253		selector = dcbcfg->app[i].selector & 0x7;1254		buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector;1255		buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF;1256		buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF;1257		/* Move to next app */1258		offset += 3;1259		i++;1260		if (i >= ICE_DCBX_MAX_APPS)1261			break;1262	}1263	/* len includes size of ouisubtype + 1 reserved + 3*numapps */1264	len = sizeof(tlv->ouisubtype) + 1 + (i * 3);1265	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF));1266	tlv->typelen = htons(typelen);1267}1268 1269/**1270 * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV1271 * @tlv: location to build the TLV data1272 * @dcbcfg: location of data to convert to TLV1273 */1274static void1275ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)1276{1277	u8 *buf = tlv->tlvinfo;1278	u32 ouisubtype;1279	u16 typelen;1280	int i;1281 1282	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1283		   ICE_DSCP_UP_TLV_LEN);1284	tlv->typelen = htons(typelen);1285 1286	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |1287			   ICE_DSCP_SUBTYPE_DSCP2UP);1288	tlv->ouisubtype = htonl(ouisubtype);1289 1290	/* bytes 0 - 63 - IPv4 DSCP2UP LUT */1291	for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {1292		/* IPv4 mapping */1293		buf[i] = dcbcfg->dscp_map[i];1294		/* IPv6 mapping */1295		buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];1296	}1297 1298	/* byte 64 - IPv4 untagged traffic */1299	buf[i] = 0;1300 1301	/* byte 144 - IPv6 untagged traffic */1302	buf[i + ICE_DSCP_IPV6_OFFSET] = 0;1303}1304 1305#define ICE_BYTES_PER_TC	81306/**1307 * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV1308 * @tlv: location to build the TLV data1309 */1310static void1311ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)1312{1313	u8 *buf = tlv->tlvinfo;1314	u32 ouisubtype;1315	u16 typelen;1316 1317	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1318		   ICE_DSCP_ENF_TLV_LEN);1319	tlv->typelen = htons(typelen);1320 1321	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |1322			   ICE_DSCP_SUBTYPE_ENFORCE);1323	tlv->ouisubtype = htonl(ouisubtype);1324 1325	/* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */1326	memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));1327}1328 1329/**1330 * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV1331 * @tlv: location to build the TLV data1332 * @dcbcfg: location of the data to convert to TLV1333 */1334static void1335ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,1336		       struct ice_dcbx_cfg *dcbcfg)1337{1338	struct ice_dcb_ets_cfg *etscfg;1339	u8 *buf = tlv->tlvinfo;1340	u32 ouisubtype;1341	u8 offset = 0;1342	u16 typelen;1343	int i;1344 1345	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1346		   ICE_DSCP_TC_BW_TLV_LEN);1347	tlv->typelen = htons(typelen);1348 1349	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |1350			   ICE_DSCP_SUBTYPE_TCBW);1351	tlv->ouisubtype = htonl(ouisubtype);1352 1353	/* First Octect after subtype1354	 * ----------------------------1355	 * | RSV | CBS | RSV | Max TCs |1356	 * | 1b  | 1b  | 3b  | 3b      |1357	 * ----------------------------1358	 */1359	etscfg = &dcbcfg->etscfg;1360	buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;1361 1362	/* bytes 1 - 4 reserved */1363	offset = 5;1364 1365	/* TC BW table1366	 * bytes 0 - 7 for TC 0 - 71367	 *1368	 * TSA Assignment table1369	 * bytes 8 - 15 for TC 0 - 71370	 */1371	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {1372		buf[offset] = etscfg->tcbwtable[i];1373		buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];1374		offset++;1375	}1376}1377 1378/**1379 * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV1380 * @tlv: Fill PFC TLV in IEEE format1381 * @dcbcfg: Local store which holds the PFC CFG data1382 */1383static void1384ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)1385{1386	u8 *buf = tlv->tlvinfo;1387	u32 ouisubtype;1388	u16 typelen;1389 1390	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |1391		   ICE_DSCP_PFC_TLV_LEN);1392	tlv->typelen = htons(typelen);1393 1394	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |1395			   ICE_DSCP_SUBTYPE_PFC);1396	tlv->ouisubtype = htonl(ouisubtype);1397 1398	buf[0] = dcbcfg->pfc.pfccap & 0xF;1399	buf[1] = dcbcfg->pfc.pfcena;1400}1401 1402/**1403 * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs1404 * @tlv: Fill TLV data in IEEE format1405 * @dcbcfg: Local store which holds the DCB Config1406 * @tlvid: Type of IEEE TLV1407 *1408 * Add tlv information1409 */1410static void1411ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,1412		u16 tlvid)1413{1414	if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {1415		switch (tlvid) {1416		case ICE_IEEE_TLV_ID_ETS_CFG:1417			ice_add_ieee_ets_tlv(tlv, dcbcfg);1418			break;1419		case ICE_IEEE_TLV_ID_ETS_REC:1420			ice_add_ieee_etsrec_tlv(tlv, dcbcfg);1421			break;1422		case ICE_IEEE_TLV_ID_PFC_CFG:1423			ice_add_ieee_pfc_tlv(tlv, dcbcfg);1424			break;1425		case ICE_IEEE_TLV_ID_APP_PRI:1426			ice_add_ieee_app_pri_tlv(tlv, dcbcfg);1427			break;1428		default:1429			break;1430		}1431	} else {1432		/* pfc_mode == ICE_QOS_MODE_DSCP */1433		switch (tlvid) {1434		case ICE_TLV_ID_DSCP_UP:1435			ice_add_dscp_up_tlv(tlv, dcbcfg);1436			break;1437		case ICE_TLV_ID_DSCP_ENF:1438			ice_add_dscp_enf_tlv(tlv);1439			break;1440		case ICE_TLV_ID_DSCP_TC_BW:1441			ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);1442			break;1443		case ICE_TLV_ID_DSCP_TO_PFC:1444			ice_add_dscp_pfc_tlv(tlv, dcbcfg);1445			break;1446		default:1447			break;1448		}1449	}1450}1451 1452/**1453 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format1454 * @lldpmib: pointer to the HW struct1455 * @miblen: length of LLDP MIB1456 * @dcbcfg: Local store which holds the DCB Config1457 *1458 * Convert the DCB configuration to MIB format1459 */1460static void1461ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg)1462{1463	u16 len, offset = 0, tlvid = ICE_TLV_ID_START;1464	struct ice_lldp_org_tlv *tlv;1465	u16 typelen;1466 1467	tlv = (struct ice_lldp_org_tlv *)lldpmib;1468	while (1) {1469		ice_add_dcb_tlv(tlv, dcbcfg, tlvid++);1470		typelen = ntohs(tlv->typelen);1471		len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen);1472		if (len)1473			offset += len + 2;1474		/* END TLV or beyond LLDPDU size */1475		if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU ||1476		    offset > ICE_LLDPDU_SIZE)1477			break;1478		/* Move to next TLV */1479		if (len)1480			tlv = (struct ice_lldp_org_tlv *)1481				((char *)tlv + sizeof(tlv->typelen) + len);1482	}1483	*miblen = offset;1484}1485 1486/**1487 * ice_set_dcb_cfg - Set the local LLDP MIB to FW1488 * @pi: port information structure1489 *1490 * Set DCB configuration to the Firmware1491 */1492int ice_set_dcb_cfg(struct ice_port_info *pi)1493{1494	u8 mib_type, *lldpmib = NULL;1495	struct ice_dcbx_cfg *dcbcfg;1496	struct ice_hw *hw;1497	u16 miblen;1498	int ret;1499 1500	if (!pi)1501		return -EINVAL;1502 1503	hw = pi->hw;1504 1505	/* update the HW local config */1506	dcbcfg = &pi->qos_cfg.local_dcbx_cfg;1507	/* Allocate the LLDPDU */1508	lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);1509	if (!lldpmib)1510		return -ENOMEM;1511 1512	mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB;1513	if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)1514		mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING;1515 1516	ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg);1517	ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen,1518				  NULL);1519 1520	devm_kfree(ice_hw_to_dev(hw), lldpmib);1521 1522	return ret;1523}1524 1525/**1526 * ice_aq_query_port_ets - query port ETS configuration1527 * @pi: port information structure1528 * @buf: pointer to buffer1529 * @buf_size: buffer size in bytes1530 * @cd: pointer to command details structure or NULL1531 *1532 * query current port ETS configuration1533 */1534static int1535ice_aq_query_port_ets(struct ice_port_info *pi,1536		      struct ice_aqc_port_ets_elem *buf, u16 buf_size,1537		      struct ice_sq_cd *cd)1538{1539	struct ice_aqc_query_port_ets *cmd;1540	struct ice_aq_desc desc;1541	int status;1542 1543	if (!pi)1544		return -EINVAL;1545	cmd = &desc.params.port_ets;1546	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets);1547	cmd->port_teid = pi->root->info.node_teid;1548 1549	status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd);1550	return status;1551}1552 1553/**1554 * ice_update_port_tc_tree_cfg - update TC tree configuration1555 * @pi: port information structure1556 * @buf: pointer to buffer1557 *1558 * update the SW DB with the new TC changes1559 */1560static int1561ice_update_port_tc_tree_cfg(struct ice_port_info *pi,1562			    struct ice_aqc_port_ets_elem *buf)1563{1564	struct ice_sched_node *node, *tc_node;1565	struct ice_aqc_txsched_elem_data elem;1566	u32 teid1, teid2;1567	int status = 0;1568	u8 i, j;1569 1570	if (!pi)1571		return -EINVAL;1572	/* suspend the missing TC nodes */1573	for (i = 0; i < pi->root->num_children; i++) {1574		teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid);1575		ice_for_each_traffic_class(j) {1576			teid2 = le32_to_cpu(buf->tc_node_teid[j]);1577			if (teid1 == teid2)1578				break;1579		}1580		if (j < ICE_MAX_TRAFFIC_CLASS)1581			continue;1582		/* TC is missing */1583		pi->root->children[i]->in_use = false;1584	}1585	/* add the new TC nodes */1586	ice_for_each_traffic_class(j) {1587		teid2 = le32_to_cpu(buf->tc_node_teid[j]);1588		if (teid2 == ICE_INVAL_TEID)1589			continue;1590		/* Is it already present in the tree ? */1591		for (i = 0; i < pi->root->num_children; i++) {1592			tc_node = pi->root->children[i];1593			if (!tc_node)1594				continue;1595			teid1 = le32_to_cpu(tc_node->info.node_teid);1596			if (teid1 == teid2) {1597				tc_node->tc_num = j;1598				tc_node->in_use = true;1599				break;1600			}1601		}1602		if (i < pi->root->num_children)1603			continue;1604		/* new TC */1605		status = ice_sched_query_elem(pi->hw, teid2, &elem);1606		if (!status)1607			status = ice_sched_add_node(pi, 1, &elem, NULL);1608		if (status)1609			break;1610		/* update the TC number */1611		node = ice_sched_find_node_by_teid(pi->root, teid2);1612		if (node)1613			node->tc_num = j;1614	}1615	return status;1616}1617 1618/**1619 * ice_query_port_ets - query port ETS configuration1620 * @pi: port information structure1621 * @buf: pointer to buffer1622 * @buf_size: buffer size in bytes1623 * @cd: pointer to command details structure or NULL1624 *1625 * query current port ETS configuration and update the1626 * SW DB with the TC changes1627 */1628int1629ice_query_port_ets(struct ice_port_info *pi,1630		   struct ice_aqc_port_ets_elem *buf, u16 buf_size,1631		   struct ice_sq_cd *cd)1632{1633	int status;1634 1635	mutex_lock(&pi->sched_lock);1636	status = ice_aq_query_port_ets(pi, buf, buf_size, cd);1637	if (!status)1638		status = ice_update_port_tc_tree_cfg(pi, buf);1639	mutex_unlock(&pi->sched_lock);1640	return status;1641}1642