brintos

brintos / linux-shallow public Read only

0
0
Text · 54.1 KiB · 8db1eb0 Raw
1929 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2013 - 2021 Intel Corporation. */3 4#include <linux/bitfield.h>5#include "i40e_adminq.h"6#include "i40e_alloc.h"7#include "i40e_dcb.h"8#include "i40e_prototype.h"9 10/**11 * i40e_get_dcbx_status12 * @hw: pointer to the hw struct13 * @status: Embedded DCBX Engine Status14 *15 * Get the DCBX status from the Firmware16 **/17int i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)18{19	u32 reg;20 21	if (!status)22		return -EINVAL;23 24	reg = rd32(hw, I40E_PRTDCB_GENS);25	*status = FIELD_GET(I40E_PRTDCB_GENS_DCBX_STATUS_MASK, reg);26 27	return 0;28}29 30/**31 * i40e_parse_ieee_etscfg_tlv32 * @tlv: IEEE 802.1Qaz ETS CFG TLV33 * @dcbcfg: Local store to update ETS CFG data34 *35 * Parses IEEE 802.1Qaz ETS CFG TLV36 **/37static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,38				       struct i40e_dcbx_config *dcbcfg)39{40	struct i40e_dcb_ets_config *etscfg;41	u8 *buf = tlv->tlvinfo;42	u16 offset = 0;43	u8 priority;44	int i;45 46	/* First Octet post subtype47	 * --------------------------48	 * |will-|CBS  | Re-  | Max |49	 * |ing  |     |served| TCs |50	 * --------------------------51	 * |1bit | 1bit|3 bits|3bits|52	 */53	etscfg = &dcbcfg->etscfg;54	etscfg->willing = FIELD_GET(I40E_IEEE_ETS_WILLING_MASK, buf[offset]);55	etscfg->cbs = FIELD_GET(I40E_IEEE_ETS_CBS_MASK, buf[offset]);56	etscfg->maxtcs = FIELD_GET(I40E_IEEE_ETS_MAXTC_MASK, buf[offset]);57 58	/* Move offset to Priority Assignment Table */59	offset++;60 61	/* Priority Assignment Table (4 octets)62	 * Octets:|    1    |    2    |    3    |    4    |63	 *        -----------------------------------------64	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|65	 *        -----------------------------------------66	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|67	 *        -----------------------------------------68	 */69	for (i = 0; i < 4; i++) {70		priority = FIELD_GET(I40E_IEEE_ETS_PRIO_1_MASK, buf[offset]);71		etscfg->prioritytable[i * 2] = priority;72		priority = FIELD_GET(I40E_IEEE_ETS_PRIO_0_MASK, buf[offset]);73		etscfg->prioritytable[i * 2 + 1] = priority;74		offset++;75	}76 77	/* TC Bandwidth Table (8 octets)78	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |79	 *        ---------------------------------80	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|81	 *        ---------------------------------82	 */83	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)84		etscfg->tcbwtable[i] = buf[offset++];85 86	/* TSA Assignment Table (8 octets)87	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |88	 *        ---------------------------------89	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|90	 *        ---------------------------------91	 */92	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)93		etscfg->tsatable[i] = buf[offset++];94}95 96/**97 * i40e_parse_ieee_etsrec_tlv98 * @tlv: IEEE 802.1Qaz ETS REC TLV99 * @dcbcfg: Local store to update ETS REC data100 *101 * Parses IEEE 802.1Qaz ETS REC TLV102 **/103static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,104				       struct i40e_dcbx_config *dcbcfg)105{106	u8 *buf = tlv->tlvinfo;107	u16 offset = 0;108	u8 priority;109	int i;110 111	/* Move offset to priority table */112	offset++;113 114	/* Priority Assignment Table (4 octets)115	 * Octets:|    1    |    2    |    3    |    4    |116	 *        -----------------------------------------117	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|118	 *        -----------------------------------------119	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|120	 *        -----------------------------------------121	 */122	for (i = 0; i < 4; i++) {123		priority = FIELD_GET(I40E_IEEE_ETS_PRIO_1_MASK, buf[offset]);124		dcbcfg->etsrec.prioritytable[i * 2] = priority;125		priority = FIELD_GET(I40E_IEEE_ETS_PRIO_0_MASK, buf[offset]);126		dcbcfg->etsrec.prioritytable[(i * 2) + 1] = priority;127		offset++;128	}129 130	/* TC Bandwidth Table (8 octets)131	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |132	 *        ---------------------------------133	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|134	 *        ---------------------------------135	 */136	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)137		dcbcfg->etsrec.tcbwtable[i] = buf[offset++];138 139	/* TSA Assignment Table (8 octets)140	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |141	 *        ---------------------------------142	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|143	 *        ---------------------------------144	 */145	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)146		dcbcfg->etsrec.tsatable[i] = buf[offset++];147}148 149/**150 * i40e_parse_ieee_pfccfg_tlv151 * @tlv: IEEE 802.1Qaz PFC CFG TLV152 * @dcbcfg: Local store to update PFC CFG data153 *154 * Parses IEEE 802.1Qaz PFC CFG TLV155 **/156static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,157				       struct i40e_dcbx_config *dcbcfg)158{159	u8 *buf = tlv->tlvinfo;160 161	/* ----------------------------------------162	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |163	 * |ing  |     |served| cap |              |164	 * -----------------------------------------165	 * |1bit | 1bit|2 bits|4bits| 1 octet      |166	 */167	dcbcfg->pfc.willing = FIELD_GET(I40E_IEEE_PFC_WILLING_MASK, buf[0]);168	dcbcfg->pfc.mbc = FIELD_GET(I40E_IEEE_PFC_MBC_MASK, buf[0]);169	dcbcfg->pfc.pfccap = FIELD_GET(I40E_IEEE_PFC_CAP_MASK, buf[0]);170	dcbcfg->pfc.pfcenable = buf[1];171}172 173/**174 * i40e_parse_ieee_app_tlv175 * @tlv: IEEE 802.1Qaz APP TLV176 * @dcbcfg: Local store to update APP PRIO data177 *178 * Parses IEEE 802.1Qaz APP PRIO TLV179 **/180static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,181				    struct i40e_dcbx_config *dcbcfg)182{183	u16 typelength;184	u16 offset = 0;185	u16 length;186	int i = 0;187	u8 *buf;188 189	typelength = ntohs(tlv->typelength);190	length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);191	buf = tlv->tlvinfo;192 193	/* The App priority table starts 5 octets after TLV header */194	length -= (sizeof(tlv->ouisubtype) + 1);195 196	/* Move offset to App Priority Table */197	offset++;198 199	/* Application Priority Table (3 octets)200	 * Octets:|         1          |    2    |    3    |201	 *        -----------------------------------------202	 *        |Priority|Rsrvd| Sel |    Protocol ID    |203	 *        -----------------------------------------204	 *   Bits:|23    21|20 19|18 16|15                0|205	 *        -----------------------------------------206	 */207	while (offset < length) {208		dcbcfg->app[i].priority = FIELD_GET(I40E_IEEE_APP_PRIO_MASK,209						    buf[offset]);210		dcbcfg->app[i].selector = FIELD_GET(I40E_IEEE_APP_SEL_MASK,211						    buf[offset]);212		dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |213					     buf[offset + 2];214		/* Move to next app */215		offset += 3;216		i++;217		if (i >= I40E_DCBX_MAX_APPS)218			break;219	}220 221	dcbcfg->numapps = i;222}223 224/**225 * i40e_parse_ieee_tlv226 * @tlv: IEEE 802.1Qaz TLV227 * @dcbcfg: Local store to update ETS REC data228 *229 * Get the TLV subtype and send it to parsing function230 * based on the subtype value231 **/232static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,233				struct i40e_dcbx_config *dcbcfg)234{235	u32 ouisubtype;236	u8 subtype;237 238	ouisubtype = ntohl(tlv->ouisubtype);239	subtype = FIELD_GET(I40E_LLDP_TLV_SUBTYPE_MASK, ouisubtype);240	switch (subtype) {241	case I40E_IEEE_SUBTYPE_ETS_CFG:242		i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);243		break;244	case I40E_IEEE_SUBTYPE_ETS_REC:245		i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);246		break;247	case I40E_IEEE_SUBTYPE_PFC_CFG:248		i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);249		break;250	case I40E_IEEE_SUBTYPE_APP_PRI:251		i40e_parse_ieee_app_tlv(tlv, dcbcfg);252		break;253	default:254		break;255	}256}257 258/**259 * i40e_parse_cee_pgcfg_tlv260 * @tlv: CEE DCBX PG CFG TLV261 * @dcbcfg: Local store to update ETS CFG data262 *263 * Parses CEE DCBX PG CFG TLV264 **/265static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,266				     struct i40e_dcbx_config *dcbcfg)267{268	struct i40e_dcb_ets_config *etscfg;269	u8 *buf = tlv->tlvinfo;270	u16 offset = 0;271	u8 priority;272	int i;273 274	etscfg = &dcbcfg->etscfg;275 276	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)277		etscfg->willing = 1;278 279	etscfg->cbs = 0;280	/* Priority Group Table (4 octets)281	 * Octets:|    1    |    2    |    3    |    4    |282	 *        -----------------------------------------283	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|284	 *        -----------------------------------------285	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|286	 *        -----------------------------------------287	 */288	for (i = 0; i < 4; i++) {289		priority = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK, buf[offset]);290		etscfg->prioritytable[i * 2] = priority;291		priority = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK, buf[offset]);292		etscfg->prioritytable[i * 2 + 1] = priority;293		offset++;294	}295 296	/* PG Percentage Table (8 octets)297	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |298	 *        ---------------------------------299	 *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|300	 *        ---------------------------------301	 */302	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)303		etscfg->tcbwtable[i] = buf[offset++];304 305	/* Number of TCs supported (1 octet) */306	etscfg->maxtcs = buf[offset];307}308 309/**310 * i40e_parse_cee_pfccfg_tlv311 * @tlv: CEE DCBX PFC CFG TLV312 * @dcbcfg: Local store to update PFC CFG data313 *314 * Parses CEE DCBX PFC CFG TLV315 **/316static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,317				      struct i40e_dcbx_config *dcbcfg)318{319	u8 *buf = tlv->tlvinfo;320 321	if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)322		dcbcfg->pfc.willing = 1;323 324	/* ------------------------325	 * | PFC Enable | PFC TCs |326	 * ------------------------327	 * | 1 octet    | 1 octet |328	 */329	dcbcfg->pfc.pfcenable = buf[0];330	dcbcfg->pfc.pfccap = buf[1];331}332 333/**334 * i40e_parse_cee_app_tlv335 * @tlv: CEE DCBX APP TLV336 * @dcbcfg: Local store to update APP PRIO data337 *338 * Parses CEE DCBX APP PRIO TLV339 **/340static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,341				   struct i40e_dcbx_config *dcbcfg)342{343	u16 length, typelength, offset = 0;344	struct i40e_cee_app_prio *app;345	u8 i;346 347	typelength = ntohs(tlv->hdr.typelen);348	length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);349 350	dcbcfg->numapps = length / sizeof(*app);351 352	if (!dcbcfg->numapps)353		return;354	if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)355		dcbcfg->numapps = I40E_DCBX_MAX_APPS;356 357	for (i = 0; i < dcbcfg->numapps; i++) {358		u8 up, selector;359 360		app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);361		for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {362			if (app->prio_map & BIT(up))363				break;364		}365		dcbcfg->app[i].priority = up;366 367		/* Get Selector from lower 2 bits, and convert to IEEE */368		selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);369		switch (selector) {370		case I40E_CEE_APP_SEL_ETHTYPE:371			dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;372			break;373		case I40E_CEE_APP_SEL_TCPIP:374			dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;375			break;376		default:377			/* Keep selector as it is for unknown types */378			dcbcfg->app[i].selector = selector;379		}380 381		dcbcfg->app[i].protocolid = ntohs(app->protocol);382		/* Move to next app */383		offset += sizeof(*app);384	}385}386 387/**388 * i40e_parse_cee_tlv389 * @tlv: CEE DCBX TLV390 * @dcbcfg: Local store to update DCBX config data391 *392 * Get the TLV subtype and send it to parsing function393 * based on the subtype value394 **/395static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,396			       struct i40e_dcbx_config *dcbcfg)397{398	u16 len, tlvlen, sublen, typelength;399	struct i40e_cee_feat_tlv *sub_tlv;400	u8 subtype, feat_tlv_count = 0;401	u32 ouisubtype;402 403	ouisubtype = ntohl(tlv->ouisubtype);404	subtype = FIELD_GET(I40E_LLDP_TLV_SUBTYPE_MASK, ouisubtype);405	/* Return if not CEE DCBX */406	if (subtype != I40E_CEE_DCBX_TYPE)407		return;408 409	typelength = ntohs(tlv->typelength);410	tlvlen = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);411	len = sizeof(tlv->typelength) + sizeof(ouisubtype) +412	      sizeof(struct i40e_cee_ctrl_tlv);413	/* Return if no CEE DCBX Feature TLVs */414	if (tlvlen <= len)415		return;416 417	sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);418	while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {419		typelength = ntohs(sub_tlv->hdr.typelen);420		sublen = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);421		subtype = FIELD_GET(I40E_LLDP_TLV_TYPE_MASK, typelength);422		switch (subtype) {423		case I40E_CEE_SUBTYPE_PG_CFG:424			i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);425			break;426		case I40E_CEE_SUBTYPE_PFC_CFG:427			i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);428			break;429		case I40E_CEE_SUBTYPE_APP_PRI:430			i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);431			break;432		default:433			return; /* Invalid Sub-type return */434		}435		feat_tlv_count++;436		/* Move to next sub TLV */437		sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +438						sizeof(sub_tlv->hdr.typelen) +439						sublen);440	}441}442 443/**444 * i40e_parse_org_tlv445 * @tlv: Organization specific TLV446 * @dcbcfg: Local store to update ETS REC data447 *448 * Currently only IEEE 802.1Qaz TLV is supported, all others449 * will be returned450 **/451static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,452			       struct i40e_dcbx_config *dcbcfg)453{454	u32 ouisubtype;455	u32 oui;456 457	ouisubtype = ntohl(tlv->ouisubtype);458	oui = FIELD_GET(I40E_LLDP_TLV_OUI_MASK, ouisubtype);459	switch (oui) {460	case I40E_IEEE_8021QAZ_OUI:461		i40e_parse_ieee_tlv(tlv, dcbcfg);462		break;463	case I40E_CEE_DCBX_OUI:464		i40e_parse_cee_tlv(tlv, dcbcfg);465		break;466	default:467		break;468	}469}470 471/**472 * i40e_lldp_to_dcb_config473 * @lldpmib: LLDPDU to be parsed474 * @dcbcfg: store for LLDPDU data475 *476 * Parse DCB configuration from the LLDPDU477 **/478int i40e_lldp_to_dcb_config(u8 *lldpmib,479			    struct i40e_dcbx_config *dcbcfg)480{481	struct i40e_lldp_org_tlv *tlv;482	u16 typelength;483	u16 offset = 0;484	int ret = 0;485	u16 length;486	u16 type;487 488	if (!lldpmib || !dcbcfg)489		return -EINVAL;490 491	/* set to the start of LLDPDU */492	lldpmib += ETH_HLEN;493	tlv = (struct i40e_lldp_org_tlv *)lldpmib;494	while (1) {495		typelength = ntohs(tlv->typelength);496		type = FIELD_GET(I40E_LLDP_TLV_TYPE_MASK, typelength);497		length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);498		offset += sizeof(typelength) + length;499 500		/* END TLV or beyond LLDPDU size */501		if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))502			break;503 504		switch (type) {505		case I40E_TLV_TYPE_ORG:506			i40e_parse_org_tlv(tlv, dcbcfg);507			break;508		default:509			break;510		}511 512		/* Move to next TLV */513		tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +514						    sizeof(tlv->typelength) +515						    length);516	}517 518	return ret;519}520 521/**522 * i40e_aq_get_dcb_config523 * @hw: pointer to the hw struct524 * @mib_type: mib type for the query525 * @bridgetype: bridge type for the query (remote)526 * @dcbcfg: store for LLDPDU data527 *528 * Query DCB configuration from the Firmware529 **/530int i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,531			   u8 bridgetype,532			   struct i40e_dcbx_config *dcbcfg)533{534	struct i40e_virt_mem mem;535	int ret = 0;536	u8 *lldpmib;537 538	/* Allocate the LLDPDU */539	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);540	if (ret)541		return ret;542 543	lldpmib = (u8 *)mem.va;544	ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,545				   (void *)lldpmib, I40E_LLDPDU_SIZE,546				   NULL, NULL, NULL);547	if (ret)548		goto free_mem;549 550	/* Parse LLDP MIB to get dcb configuration */551	ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);552 553free_mem:554	i40e_free_virt_mem(hw, &mem);555	return ret;556}557 558/**559 * i40e_cee_to_dcb_v1_config560 * @cee_cfg: pointer to CEE v1 response configuration struct561 * @dcbcfg: DCB configuration struct562 *563 * Convert CEE v1 configuration from firmware to DCB configuration564 **/565static void i40e_cee_to_dcb_v1_config(566			struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,567			struct i40e_dcbx_config *dcbcfg)568{569	u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);570	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);571	u8 i, err;572 573	/* CEE PG data to ETS config */574	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;575 576	/* Note that the FW creates the oper_prio_tc nibbles reversed577	 * from those in the CEE Priority Group sub-TLV.578	 */579	for (i = 0; i < 4; i++) {580		u8 tc;581 582		tc = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK,583			       cee_cfg->oper_prio_tc[i]);584		dcbcfg->etscfg.prioritytable[i * 2] = tc;585		tc = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK,586			       cee_cfg->oper_prio_tc[i]);587		dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;588	}589 590	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)591		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];592 593	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {594		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {595			/* Map it to next empty TC */596			dcbcfg->etscfg.prioritytable[i] =597						cee_cfg->oper_num_tc - 1;598			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;599		} else {600			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;601		}602	}603 604	/* CEE PFC data to ETS config */605	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;606	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;607 608	status = FIELD_GET(I40E_AQC_CEE_APP_STATUS_MASK, tlv_status);609	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;610	/* Add APPs if Error is False */611	if (!err) {612		/* CEE operating configuration supports FCoE/iSCSI/FIP only */613		dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;614 615		/* FCoE APP */616		dcbcfg->app[0].priority =617			FIELD_GET(I40E_AQC_CEE_APP_FCOE_MASK, app_prio);618		dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;619		dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;620 621		/* iSCSI APP */622		dcbcfg->app[1].priority =623			FIELD_GET(I40E_AQC_CEE_APP_ISCSI_MASK, app_prio);624		dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;625		dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;626 627		/* FIP APP */628		dcbcfg->app[2].priority =629			FIELD_GET(I40E_AQC_CEE_APP_FIP_MASK, app_prio);630		dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;631		dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;632	}633}634 635/**636 * i40e_cee_to_dcb_config637 * @cee_cfg: pointer to CEE configuration struct638 * @dcbcfg: DCB configuration struct639 *640 * Convert CEE configuration from firmware to DCB configuration641 **/642static void i40e_cee_to_dcb_config(643				struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,644				struct i40e_dcbx_config *dcbcfg)645{646	u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);647	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);648	u8 i, err, sync, oper;649 650	/* CEE PG data to ETS config */651	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;652 653	/* Note that the FW creates the oper_prio_tc nibbles reversed654	 * from those in the CEE Priority Group sub-TLV.655	 */656	for (i = 0; i < 4; i++) {657		u8 tc;658 659		tc = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK,660			       cee_cfg->oper_prio_tc[i]);661		dcbcfg->etscfg.prioritytable[i * 2] = tc;662		tc = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK,663			       cee_cfg->oper_prio_tc[i]);664		dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;665	}666 667	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)668		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];669 670	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {671		if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {672			/* Map it to next empty TC */673			dcbcfg->etscfg.prioritytable[i] =674						cee_cfg->oper_num_tc - 1;675			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;676		} else {677			dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;678		}679	}680 681	/* CEE PFC data to ETS config */682	dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;683	dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;684 685	i = 0;686	status = FIELD_GET(I40E_AQC_CEE_FCOE_STATUS_MASK, tlv_status);687	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;688	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;689	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;690	/* Add FCoE APP if Error is False and Oper/Sync is True */691	if (!err && sync && oper) {692		/* FCoE APP */693		dcbcfg->app[i].priority =694			FIELD_GET(I40E_AQC_CEE_APP_FCOE_MASK, app_prio);695		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;696		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;697		i++;698	}699 700	status = FIELD_GET(I40E_AQC_CEE_ISCSI_STATUS_MASK, tlv_status);701	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;702	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;703	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;704	/* Add iSCSI APP if Error is False and Oper/Sync is True */705	if (!err && sync && oper) {706		/* iSCSI APP */707		dcbcfg->app[i].priority =708			FIELD_GET(I40E_AQC_CEE_APP_ISCSI_MASK, app_prio);709		dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;710		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;711		i++;712	}713 714	status = FIELD_GET(I40E_AQC_CEE_FIP_STATUS_MASK, tlv_status);715	err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;716	sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;717	oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;718	/* Add FIP APP if Error is False and Oper/Sync is True */719	if (!err && sync && oper) {720		/* FIP APP */721		dcbcfg->app[i].priority =722			FIELD_GET(I40E_AQC_CEE_APP_FIP_MASK, app_prio);723		dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;724		dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;725		i++;726	}727	dcbcfg->numapps = i;728}729 730/**731 * i40e_get_ieee_dcb_config732 * @hw: pointer to the hw struct733 *734 * Get IEEE mode DCB configuration from the Firmware735 **/736static int i40e_get_ieee_dcb_config(struct i40e_hw *hw)737{738	int ret = 0;739 740	/* IEEE mode */741	hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;742	/* Get Local DCB Config */743	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,744				     &hw->local_dcbx_config);745	if (ret)746		goto out;747 748	/* Get Remote DCB Config */749	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,750				     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,751				     &hw->remote_dcbx_config);752	/* Don't treat ENOENT as an error for Remote MIBs */753	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)754		ret = 0;755 756out:757	return ret;758}759 760/**761 * i40e_get_dcb_config762 * @hw: pointer to the hw struct763 *764 * Get DCB configuration from the Firmware765 **/766int i40e_get_dcb_config(struct i40e_hw *hw)767{768	struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;769	struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;770	int ret = 0;771 772	/* If Firmware version < v4.33 on X710/XL710, IEEE only */773	if (hw->mac.type == I40E_MAC_XL710 && i40e_is_fw_ver_lt(hw, 4, 33))774		return i40e_get_ieee_dcb_config(hw);775 776	/* If Firmware version == v4.33 on X710/XL710, use old CEE struct */777	if (hw->mac.type == I40E_MAC_XL710 && i40e_is_fw_ver_eq(hw, 4, 33)) {778		ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,779						 sizeof(cee_v1_cfg), NULL);780		if (!ret) {781			/* CEE mode */782			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;783			hw->local_dcbx_config.tlv_status =784					le16_to_cpu(cee_v1_cfg.tlv_status);785			i40e_cee_to_dcb_v1_config(&cee_v1_cfg,786						  &hw->local_dcbx_config);787		}788	} else {789		ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,790						 sizeof(cee_cfg), NULL);791		if (!ret) {792			/* CEE mode */793			hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;794			hw->local_dcbx_config.tlv_status =795					le32_to_cpu(cee_cfg.tlv_status);796			i40e_cee_to_dcb_config(&cee_cfg,797					       &hw->local_dcbx_config);798		}799	}800 801	/* CEE mode not enabled try querying IEEE data */802	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)803		return i40e_get_ieee_dcb_config(hw);804 805	if (ret)806		goto out;807 808	/* Get CEE DCB Desired Config */809	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,810				     &hw->desired_dcbx_config);811	if (ret)812		goto out;813 814	/* Get Remote DCB Config */815	ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,816				     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,817				     &hw->remote_dcbx_config);818	/* Don't treat ENOENT as an error for Remote MIBs */819	if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)820		ret = 0;821 822out:823	return ret;824}825 826/**827 * i40e_init_dcb828 * @hw: pointer to the hw struct829 * @enable_mib_change: enable mib change event830 *831 * Update DCB configuration from the Firmware832 **/833int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)834{835	struct i40e_lldp_variables lldp_cfg;836	u8 adminstatus = 0;837	int ret = 0;838 839	if (!hw->func_caps.dcb)840		return -EOPNOTSUPP;841 842	/* Read LLDP NVM area */843	if (test_bit(I40E_HW_CAP_FW_LLDP_PERSISTENT, hw->caps)) {844		u8 offset = 0;845 846		if (hw->mac.type == I40E_MAC_XL710)847			offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;848		else if (hw->mac.type == I40E_MAC_X722)849			offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;850		else851			return -EOPNOTSUPP;852 853		ret = i40e_read_nvm_module_data(hw,854						I40E_SR_EMP_SR_SETTINGS_PTR,855						offset,856						I40E_LLDP_CURRENT_STATUS_OFFSET,857						I40E_LLDP_CURRENT_STATUS_SIZE,858						&lldp_cfg.adminstatus);859	} else {860		ret = i40e_read_lldp_cfg(hw, &lldp_cfg);861	}862	if (ret)863		return -EBUSY;864 865	/* Get the LLDP AdminStatus for the current port */866	adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);867	adminstatus &= 0xF;868 869	/* LLDP agent disabled */870	if (!adminstatus) {871		hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;872		return -EBUSY;873	}874 875	/* Get DCBX status */876	ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);877	if (ret)878		return ret;879 880	/* Check the DCBX Status */881	if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||882	    hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {883		/* Get current DCBX configuration */884		ret = i40e_get_dcb_config(hw);885		if (ret)886			return ret;887	} else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {888		return -EBUSY;889	}890 891	/* Configure the LLDP MIB change event */892	if (enable_mib_change)893		ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);894 895	return ret;896}897 898/**899 * i40e_get_fw_lldp_status900 * @hw: pointer to the hw struct901 * @lldp_status: pointer to the status enum902 *903 * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.904 * Status of agent is reported via @lldp_status parameter.905 **/906int907i40e_get_fw_lldp_status(struct i40e_hw *hw,908			enum i40e_get_fw_lldp_status_resp *lldp_status)909{910	struct i40e_virt_mem mem;911	u8 *lldpmib;912	int ret;913 914	if (!lldp_status)915		return -EINVAL;916 917	/* Allocate buffer for the LLDPDU */918	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);919	if (ret)920		return ret;921 922	lldpmib = (u8 *)mem.va;923	ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,924				   I40E_LLDPDU_SIZE, NULL, NULL, NULL);925 926	if (!ret) {927		*lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;928	} else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {929		/* MIB is not available yet but the agent is running */930		*lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;931		ret = 0;932	} else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {933		*lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;934		ret = 0;935	}936 937	i40e_free_virt_mem(hw, &mem);938	return ret;939}940 941/**942 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format943 * @tlv: Fill the ETS config data in IEEE format944 * @dcbcfg: Local store which holds the DCB Config945 *946 * Prepare IEEE 802.1Qaz ETS CFG TLV947 **/948static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,949				  struct i40e_dcbx_config *dcbcfg)950{951	u8 priority0, priority1, maxtcwilling = 0;952	struct i40e_dcb_ets_config *etscfg;953	u16 offset = 0, typelength, i;954	u8 *buf = tlv->tlvinfo;955	u32 ouisubtype;956 957	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |958			I40E_IEEE_ETS_TLV_LENGTH);959	tlv->typelength = htons(typelength);960 961	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |962			I40E_IEEE_SUBTYPE_ETS_CFG);963	tlv->ouisubtype = htonl(ouisubtype);964 965	/* First Octet post subtype966	 * --------------------------967	 * |will-|CBS  | Re-  | Max |968	 * |ing  |     |served| TCs |969	 * --------------------------970	 * |1bit | 1bit|3 bits|3bits|971	 */972	etscfg = &dcbcfg->etscfg;973	if (etscfg->willing)974		maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);975	maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;976	buf[offset] = maxtcwilling;977 978	/* Move offset to Priority Assignment Table */979	offset++;980 981	/* Priority Assignment Table (4 octets)982	 * Octets:|    1    |    2    |    3    |    4    |983	 *        -----------------------------------------984	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|985	 *        -----------------------------------------986	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|987	 *        -----------------------------------------988	 */989	for (i = 0; i < 4; i++) {990		priority0 = etscfg->prioritytable[i * 2] & 0xF;991		priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;992		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |993				priority1;994		offset++;995	}996 997	/* TC Bandwidth Table (8 octets)998	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |999	 *        ---------------------------------1000	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1001	 *        ---------------------------------1002	 */1003	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)1004		buf[offset++] = etscfg->tcbwtable[i];1005 1006	/* TSA Assignment Table (8 octets)1007	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |1008	 *        ---------------------------------1009	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1010	 *        ---------------------------------1011	 */1012	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)1013		buf[offset++] = etscfg->tsatable[i];1014}1015 1016/**1017 * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format1018 * @tlv: Fill ETS Recommended TLV in IEEE format1019 * @dcbcfg: Local store which holds the DCB Config1020 *1021 * Prepare IEEE 802.1Qaz ETS REC TLV1022 **/1023static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,1024				     struct i40e_dcbx_config *dcbcfg)1025{1026	struct i40e_dcb_ets_config *etsrec;1027	u16 offset = 0, typelength, i;1028	u8 priority0, priority1;1029	u8 *buf = tlv->tlvinfo;1030	u32 ouisubtype;1031 1032	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |1033			I40E_IEEE_ETS_TLV_LENGTH);1034	tlv->typelength = htons(typelength);1035 1036	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |1037			I40E_IEEE_SUBTYPE_ETS_REC);1038	tlv->ouisubtype = htonl(ouisubtype);1039 1040	etsrec = &dcbcfg->etsrec;1041	/* First Octet is reserved */1042	/* Move offset to Priority Assignment Table */1043	offset++;1044 1045	/* Priority Assignment Table (4 octets)1046	 * Octets:|    1    |    2    |    3    |    4    |1047	 *        -----------------------------------------1048	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|1049	 *        -----------------------------------------1050	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|1051	 *        -----------------------------------------1052	 */1053	for (i = 0; i < 4; i++) {1054		priority0 = etsrec->prioritytable[i * 2] & 0xF;1055		priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;1056		buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |1057				priority1;1058		offset++;1059	}1060 1061	/* TC Bandwidth Table (8 octets)1062	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |1063	 *        ---------------------------------1064	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1065	 *        ---------------------------------1066	 */1067	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)1068		buf[offset++] = etsrec->tcbwtable[i];1069 1070	/* TSA Assignment Table (8 octets)1071	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |1072	 *        ---------------------------------1073	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|1074	 *        ---------------------------------1075	 */1076	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)1077		buf[offset++] = etsrec->tsatable[i];1078}1079 1080/**1081 * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format1082 * @tlv: Fill PFC TLV in IEEE format1083 * @dcbcfg: Local store to get PFC CFG data1084 *1085 * Prepare IEEE 802.1Qaz PFC CFG TLV1086 **/1087static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,1088				  struct i40e_dcbx_config *dcbcfg)1089{1090	u8 *buf = tlv->tlvinfo;1091	u32 ouisubtype;1092	u16 typelength;1093 1094	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |1095			I40E_IEEE_PFC_TLV_LENGTH);1096	tlv->typelength = htons(typelength);1097 1098	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |1099			I40E_IEEE_SUBTYPE_PFC_CFG);1100	tlv->ouisubtype = htonl(ouisubtype);1101 1102	/* ----------------------------------------1103	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |1104	 * |ing  |     |served| cap |              |1105	 * -----------------------------------------1106	 * |1bit | 1bit|2 bits|4bits| 1 octet      |1107	 */1108	if (dcbcfg->pfc.willing)1109		buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);1110 1111	if (dcbcfg->pfc.mbc)1112		buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);1113 1114	buf[0] |= dcbcfg->pfc.pfccap & 0xF;1115	buf[1] = dcbcfg->pfc.pfcenable;1116}1117 1118/**1119 * i40e_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format1120 * @tlv: Fill APP TLV in IEEE format1121 * @dcbcfg: Local store to get APP CFG data1122 *1123 * Prepare IEEE 802.1Qaz APP CFG TLV1124 **/1125static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,1126				      struct i40e_dcbx_config *dcbcfg)1127{1128	u16 typelength, length, offset = 0;1129	u8 priority, selector, i = 0;1130	u8 *buf = tlv->tlvinfo;1131	u32 ouisubtype;1132 1133	/* No APP TLVs then just return */1134	if (dcbcfg->numapps == 0)1135		return;1136	ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |1137			I40E_IEEE_SUBTYPE_APP_PRI);1138	tlv->ouisubtype = htonl(ouisubtype);1139 1140	/* Move offset to App Priority Table */1141	offset++;1142	/* Application Priority Table (3 octets)1143	 * Octets:|         1          |    2    |    3    |1144	 *        -----------------------------------------1145	 *        |Priority|Rsrvd| Sel |    Protocol ID    |1146	 *        -----------------------------------------1147	 *   Bits:|23    21|20 19|18 16|15                0|1148	 *        -----------------------------------------1149	 */1150	while (i < dcbcfg->numapps) {1151		priority = dcbcfg->app[i].priority & 0x7;1152		selector = dcbcfg->app[i].selector & 0x7;1153		buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;1154		buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;1155		buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;1156		/* Move to next app */1157		offset += 3;1158		i++;1159		if (i >= I40E_DCBX_MAX_APPS)1160			break;1161	}1162	/* length includes size of ouisubtype + 1 reserved + 3*numapps */1163	length = sizeof(tlv->ouisubtype) + 1 + (i * 3);1164	typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |1165		(length & 0x1FF));1166	tlv->typelength = htons(typelength);1167}1168 1169/**1170 * i40e_add_dcb_tlv - Add all IEEE TLVs1171 * @tlv: pointer to org tlv1172 * @dcbcfg: pointer to modified dcbx config structure *1173 * @tlvid: tlv id to be added1174 * add tlv information1175 **/1176static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,1177			     struct i40e_dcbx_config *dcbcfg,1178			     u16 tlvid)1179{1180	switch (tlvid) {1181	case I40E_IEEE_TLV_ID_ETS_CFG:1182		i40e_add_ieee_ets_tlv(tlv, dcbcfg);1183		break;1184	case I40E_IEEE_TLV_ID_ETS_REC:1185		i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);1186		break;1187	case I40E_IEEE_TLV_ID_PFC_CFG:1188		i40e_add_ieee_pfc_tlv(tlv, dcbcfg);1189		break;1190	case I40E_IEEE_TLV_ID_APP_PRI:1191		i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);1192		break;1193	default:1194		break;1195	}1196}1197 1198/**1199 * i40e_set_dcb_config - Set the local LLDP MIB to FW1200 * @hw: pointer to the hw struct1201 *1202 * Set DCB configuration to the Firmware1203 **/1204int i40e_set_dcb_config(struct i40e_hw *hw)1205{1206	struct i40e_dcbx_config *dcbcfg;1207	struct i40e_virt_mem mem;1208	u8 mib_type, *lldpmib;1209	u16 miblen;1210	int ret;1211 1212	/* update the hw local config */1213	dcbcfg = &hw->local_dcbx_config;1214	/* Allocate the LLDPDU */1215	ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);1216	if (ret)1217		return ret;1218 1219	mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;1220	if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {1221		mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<1222			    SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;1223	}1224	lldpmib = (u8 *)mem.va;1225	i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);1226	ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);1227 1228	i40e_free_virt_mem(hw, &mem);1229	return ret;1230}1231 1232/**1233 * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format1234 * @lldpmib: pointer to mib to be output1235 * @miblen: pointer to u16 for length of lldpmib1236 * @dcbcfg: store for LLDPDU data1237 *1238 * send DCB configuration to FW1239 **/1240int i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,1241			    struct i40e_dcbx_config *dcbcfg)1242{1243	u16 length, offset = 0, tlvid, typelength;1244	struct i40e_lldp_org_tlv *tlv;1245 1246	tlv = (struct i40e_lldp_org_tlv *)lldpmib;1247	tlvid = I40E_TLV_ID_START;1248	do {1249		i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);1250		typelength = ntohs(tlv->typelength);1251		length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);1252		if (length)1253			offset += length + I40E_IEEE_TLV_HEADER_LENGTH;1254		/* END TLV or beyond LLDPDU size */1255		if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU ||1256		    offset >= I40E_LLDPDU_SIZE)1257			break;1258		/* Move to next TLV */1259		if (length)1260			tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +1261			      sizeof(tlv->typelength) + length);1262	} while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU);1263	*miblen = offset;1264	return 0;1265}1266 1267/**1268 * i40e_dcb_hw_rx_fifo_config1269 * @hw: pointer to the hw struct1270 * @ets_mode: Strict Priority or Round Robin mode1271 * @non_ets_mode: Strict Priority or Round Robin1272 * @max_exponent: Exponent to calculate max refill credits1273 * @lltc_map: Low latency TC bitmap1274 *1275 * Configure HW Rx FIFO as part of DCB configuration.1276 **/1277void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,1278				enum i40e_dcb_arbiter_mode ets_mode,1279				enum i40e_dcb_arbiter_mode non_ets_mode,1280				u32 max_exponent,1281				u8 lltc_map)1282{1283	u32 reg = rd32(hw, I40E_PRTDCB_RETSC);1284 1285	reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;1286	reg |= FIELD_PREP(I40E_PRTDCB_RETSC_ETS_MODE_MASK, ets_mode);1287 1288	reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;1289	reg |= FIELD_PREP(I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK, non_ets_mode);1290 1291	reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;1292	reg |= FIELD_PREP(I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK, max_exponent);1293 1294	reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;1295	reg |= FIELD_PREP(I40E_PRTDCB_RETSC_LLTC_MASK, lltc_map);1296	wr32(hw, I40E_PRTDCB_RETSC, reg);1297}1298 1299/**1300 * i40e_dcb_hw_rx_cmd_monitor_config1301 * @hw: pointer to the hw struct1302 * @num_tc: Total number of traffic class1303 * @num_ports: Total number of ports on device1304 *1305 * Configure HW Rx command monitor as part of DCB configuration.1306 **/1307void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,1308				       u8 num_tc, u8 num_ports)1309{1310	u32 threshold;1311	u32 fifo_size;1312	u32 reg;1313 1314	/* Set the threshold and fifo_size based on number of ports */1315	switch (num_ports) {1316	case 1:1317		threshold = I40E_DCB_1_PORT_THRESHOLD;1318		fifo_size = I40E_DCB_1_PORT_FIFO_SIZE;1319		break;1320	case 2:1321		if (num_tc > 4) {1322			threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC;1323			fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC;1324		} else {1325			threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC;1326			fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC;1327		}1328		break;1329	case 4:1330		if (num_tc > 4) {1331			threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC;1332			fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC;1333		} else {1334			threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC;1335			fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC;1336		}1337		break;1338	default:1339		i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n",1340			   (u32)num_ports);1341		return;1342	}1343 1344	/* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR1345	 * based on the number of ports and traffic classes for a given port as1346	 * part of DCB configuration.1347	 */1348	reg = rd32(hw, I40E_PRT_SWR_PM_THR);1349	reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;1350	reg |= FIELD_PREP(I40E_PRT_SWR_PM_THR_THRESHOLD_MASK, threshold);1351	wr32(hw, I40E_PRT_SWR_PM_THR, reg);1352 1353	reg = rd32(hw, I40E_PRTDCB_RPPMC);1354	reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;1355	reg |= FIELD_PREP(I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK, fifo_size);1356	wr32(hw, I40E_PRTDCB_RPPMC, reg);1357}1358 1359/**1360 * i40e_dcb_hw_pfc_config1361 * @hw: pointer to the hw struct1362 * @pfc_en: Bitmap of PFC enabled priorities1363 * @prio_tc: priority to tc assignment indexed by priority1364 *1365 * Configure HW Priority Flow Controller as part of DCB configuration.1366 **/1367void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,1368			    u8 pfc_en, u8 *prio_tc)1369{1370	u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2;1371	u32 link_speed = hw->phy.link_info.link_speed;1372	u8 first_pfc_prio = 0;1373	u8 num_pfc_tc = 0;1374	u8 tc2pfc = 0;1375	u32 reg;1376	u8 i;1377 1378	/* Get Number of PFC TCs and TC2PFC map */1379	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {1380		if (pfc_en & BIT(i)) {1381			if (!first_pfc_prio)1382				first_pfc_prio = i;1383			/* Set bit for the PFC TC */1384			tc2pfc |= BIT(prio_tc[i]);1385			num_pfc_tc++;1386		}1387	}1388 1389	switch (link_speed) {1390	case I40E_LINK_SPEED_10GB:1391		reg = rd32(hw, I40E_PRTDCB_MFLCN);1392		reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) &1393			I40E_PRTDCB_MFLCN_DPF_MASK;1394		reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;1395		reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;1396		if (pfc_en) {1397			reg |= FIELD_PREP(I40E_PRTDCB_MFLCN_RPFCM_MASK, 1);1398			reg |= FIELD_PREP(I40E_PRTDCB_MFLCN_RPFCE_MASK,1399					  pfc_en);1400		}1401		wr32(hw, I40E_PRTDCB_MFLCN, reg);1402 1403		reg = rd32(hw, I40E_PRTDCB_FCCFG);1404		reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;1405		if (pfc_en)1406			reg |= FIELD_PREP(I40E_PRTDCB_FCCFG_TFCE_MASK,1407					  I40E_DCB_PFC_ENABLED);1408		wr32(hw, I40E_PRTDCB_FCCFG, reg);1409 1410		/* FCTTV and FCRTV to be set by default */1411		break;1412	case I40E_LINK_SPEED_40GB:1413		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);1414		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;1415		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);1416 1417		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);1418		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;1419		reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &1420			I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK;1421		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);1422 1423		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);1424		reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;1425		reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK,1426				  pfc_en);1427		wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);1428 1429		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);1430		reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;1431		reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK,1432				  pfc_en);1433		wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);1434 1435		for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {1436			reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));1437			reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;1438			if (pfc_en) {1439				reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK,1440						  refresh_time);1441			}1442			wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);1443		}1444		/* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF1445		 * for all user priorities1446		 */1447		break;1448	}1449 1450	reg = rd32(hw, I40E_PRTDCB_TC2PFC);1451	reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;1452	reg |= FIELD_PREP(I40E_PRTDCB_TC2PFC_TC2PFC_MASK, tc2pfc);1453	wr32(hw, I40E_PRTDCB_TC2PFC, reg);1454 1455	reg = rd32(hw, I40E_PRTDCB_RUP);1456	reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;1457	reg |= FIELD_PREP(I40E_PRTDCB_RUP_NOVLANUP_MASK, first_pfc_prio);1458	wr32(hw, I40E_PRTDCB_RUP, reg);1459 1460	reg = rd32(hw, I40E_PRTDCB_TDPMC);1461	reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;1462	if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {1463		reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &1464			I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;1465	}1466	wr32(hw, I40E_PRTDCB_TDPMC, reg);1467 1468	reg = rd32(hw, I40E_PRTDCB_TCPMC);1469	reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;1470	if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {1471		reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &1472			I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;1473	}1474	wr32(hw, I40E_PRTDCB_TCPMC, reg);1475}1476 1477/**1478 * i40e_dcb_hw_set_num_tc1479 * @hw: pointer to the hw struct1480 * @num_tc: number of traffic classes1481 *1482 * Configure number of traffic classes in HW1483 **/1484void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)1485{1486	u32 reg = rd32(hw, I40E_PRTDCB_GENC);1487 1488	reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;1489	reg |= FIELD_PREP(I40E_PRTDCB_GENC_NUMTC_MASK, num_tc);1490	wr32(hw, I40E_PRTDCB_GENC, reg);1491}1492 1493/**1494 * i40e_dcb_hw_get_num_tc1495 * @hw: pointer to the hw struct1496 *1497 * Returns number of traffic classes configured in HW1498 **/1499u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)1500{1501	u32 reg = rd32(hw, I40E_PRTDCB_GENC);1502 1503	return FIELD_GET(I40E_PRTDCB_GENC_NUMTC_MASK, reg);1504}1505 1506/**1507 * i40e_dcb_hw_rx_ets_bw_config1508 * @hw: pointer to the hw struct1509 * @bw_share: Bandwidth share indexed per traffic class1510 * @mode: Strict Priority or Round Robin mode between UP sharing same1511 * traffic class1512 * @prio_type: TC is ETS enabled or strict priority1513 *1514 * Configure HW Rx ETS bandwidth as part of DCB configuration.1515 **/1516void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,1517				  u8 *mode, u8 *prio_type)1518{1519	u32 reg;1520	u8 i;1521 1522	for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {1523		reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));1524		reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK     |1525			 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |1526			 I40E_PRTDCB_RETSTCC_ETSTC_MASK);1527		reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_BWSHARE_MASK,1528				  bw_share[i]);1529		reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK,1530				  mode[i]);1531		reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_ETSTC_MASK,1532				  prio_type[i]);1533		wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);1534	}1535}1536 1537/**1538 * i40e_dcb_hw_rx_up2tc_config1539 * @hw: pointer to the hw struct1540 * @prio_tc: priority to tc assignment indexed by priority1541 *1542 * Configure HW Rx UP2TC map as part of DCB configuration.1543 **/1544void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)1545{1546	u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC);1547#define I40E_UP2TC_REG(val, i) \1548		(((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \1549		  I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)1550 1551	reg |= I40E_UP2TC_REG(prio_tc[0], 0);1552	reg |= I40E_UP2TC_REG(prio_tc[1], 1);1553	reg |= I40E_UP2TC_REG(prio_tc[2], 2);1554	reg |= I40E_UP2TC_REG(prio_tc[3], 3);1555	reg |= I40E_UP2TC_REG(prio_tc[4], 4);1556	reg |= I40E_UP2TC_REG(prio_tc[5], 5);1557	reg |= I40E_UP2TC_REG(prio_tc[6], 6);1558	reg |= I40E_UP2TC_REG(prio_tc[7], 7);1559 1560	wr32(hw, I40E_PRTDCB_RUP2TC, reg);1561}1562 1563/**1564 * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes1565 * @hw: pointer to the hw struct1566 * @num_ports: Number of available ports on the device1567 * @eee_enabled: EEE enabled for the given port1568 * @pfc_en: Bit map of PFC enabled traffic classes1569 * @mfs_tc: Array of max frame size for each traffic class1570 * @pb_cfg: pointer to packet buffer configuration1571 *1572 * Calculate the shared and dedicated per TC pool sizes,1573 * watermarks and threshold values.1574 **/1575void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,1576				      u8 num_ports, bool eee_enabled,1577				      u8 pfc_en, u32 *mfs_tc,1578				      struct i40e_rx_pb_config *pb_cfg)1579{1580	u32 pool_size[I40E_MAX_TRAFFIC_CLASS];1581	u32 high_wm[I40E_MAX_TRAFFIC_CLASS];1582	u32 low_wm[I40E_MAX_TRAFFIC_CLASS];1583	u32 total_pool_size = 0;1584	int shared_pool_size; /* Need signed variable */1585	u32 port_pb_size;1586	u32 mfs_max = 0;1587	u32 pcirtt;1588	u8 i;1589 1590	/* Get the MFS(max) for the port */1591	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1592		if (mfs_tc[i] > mfs_max)1593			mfs_max = mfs_tc[i];1594	}1595 1596	pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);1597 1598	/* Calculate effective Rx PB size per port */1599	port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports;1600	if (eee_enabled)1601		port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);1602	port_pb_size -= mfs_max;1603 1604	/* Step 1 Calculating tc pool/shared pool sizes and watermarks */1605	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1606		if (pfc_en & BIT(i)) {1607			low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR *1608				     mfs_tc[i]) + pcirtt;1609			high_wm[i] = low_wm[i];1610			high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)1611					? mfs_max : I40E_MAX_FRAME_SIZE);1612			pool_size[i] = high_wm[i];1613			pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,1614								mfs_tc[i]));1615		} else {1616			low_wm[i] = 0;1617			pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR *1618					mfs_tc[i]) + pcirtt;1619			high_wm[i] = pool_size[i];1620		}1621		total_pool_size += pool_size[i];1622	}1623 1624	shared_pool_size = port_pb_size - total_pool_size;1625	if (shared_pool_size > 0) {1626		pb_cfg->shared_pool_size = shared_pool_size;1627		pb_cfg->shared_pool_high_wm = shared_pool_size;1628		pb_cfg->shared_pool_low_wm = 0;1629		for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1630			pb_cfg->shared_pool_low_thresh[i] = 0;1631			pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;1632			pb_cfg->tc_pool_size[i] = pool_size[i];1633			pb_cfg->tc_pool_high_wm[i] = high_wm[i];1634			pb_cfg->tc_pool_low_wm[i] = low_wm[i];1635		}1636 1637	} else {1638		i40e_debug(hw, I40E_DEBUG_DCB,1639			   "The shared pool size for the port is negative %d.\n",1640			   shared_pool_size);1641	}1642}1643 1644/**1645 * i40e_dcb_hw_rx_pb_config1646 * @hw: pointer to the hw struct1647 * @old_pb_cfg: Existing Rx Packet buffer configuration1648 * @new_pb_cfg: New Rx Packet buffer configuration1649 *1650 * Program the Rx Packet Buffer registers.1651 **/1652void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,1653			      struct i40e_rx_pb_config *old_pb_cfg,1654			      struct i40e_rx_pb_config *new_pb_cfg)1655{1656	u32 old_val;1657	u32 new_val;1658	u32 reg;1659	u8 i;1660 1661	/* The Rx Packet buffer register programming needs to be done in a1662	 * certain order and the following code is based on that1663	 * requirement.1664	 */1665 1666	/* Program the shared pool low water mark per port if decreasing */1667	old_val = old_pb_cfg->shared_pool_low_wm;1668	new_val = new_pb_cfg->shared_pool_low_wm;1669	if (new_val < old_val) {1670		reg = rd32(hw, I40E_PRTRPB_SLW);1671		reg &= ~I40E_PRTRPB_SLW_SLW_MASK;1672		reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val);1673		wr32(hw, I40E_PRTRPB_SLW, reg);1674	}1675 1676	/* Program the shared pool low threshold and tc pool1677	 * low water mark per TC that are decreasing.1678	 */1679	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1680		old_val = old_pb_cfg->shared_pool_low_thresh[i];1681		new_val = new_pb_cfg->shared_pool_low_thresh[i];1682		if (new_val < old_val) {1683			reg = rd32(hw, I40E_PRTRPB_SLT(i));1684			reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;1685			reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK,1686					  new_val);1687			wr32(hw, I40E_PRTRPB_SLT(i), reg);1688		}1689 1690		old_val = old_pb_cfg->tc_pool_low_wm[i];1691		new_val = new_pb_cfg->tc_pool_low_wm[i];1692		if (new_val < old_val) {1693			reg = rd32(hw, I40E_PRTRPB_DLW(i));1694			reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;1695			reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK,1696					  new_val);1697			wr32(hw, I40E_PRTRPB_DLW(i), reg);1698		}1699	}1700 1701	/* Program the shared pool high water mark per port if decreasing */1702	old_val = old_pb_cfg->shared_pool_high_wm;1703	new_val = new_pb_cfg->shared_pool_high_wm;1704	if (new_val < old_val) {1705		reg = rd32(hw, I40E_PRTRPB_SHW);1706		reg &= ~I40E_PRTRPB_SHW_SHW_MASK;1707		reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val);1708		wr32(hw, I40E_PRTRPB_SHW, reg);1709	}1710 1711	/* Program the shared pool high threshold and tc pool1712	 * high water mark per TC that are decreasing.1713	 */1714	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1715		old_val = old_pb_cfg->shared_pool_high_thresh[i];1716		new_val = new_pb_cfg->shared_pool_high_thresh[i];1717		if (new_val < old_val) {1718			reg = rd32(hw, I40E_PRTRPB_SHT(i));1719			reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;1720			reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK,1721					  new_val);1722			wr32(hw, I40E_PRTRPB_SHT(i), reg);1723		}1724 1725		old_val = old_pb_cfg->tc_pool_high_wm[i];1726		new_val = new_pb_cfg->tc_pool_high_wm[i];1727		if (new_val < old_val) {1728			reg = rd32(hw, I40E_PRTRPB_DHW(i));1729			reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;1730			reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK,1731					  new_val);1732			wr32(hw, I40E_PRTRPB_DHW(i), reg);1733		}1734	}1735 1736	/* Write Dedicated Pool Sizes per TC */1737	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1738		new_val = new_pb_cfg->tc_pool_size[i];1739		reg = rd32(hw, I40E_PRTRPB_DPS(i));1740		reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;1741		reg |= FIELD_PREP(I40E_PRTRPB_DPS_DPS_TCN_MASK, new_val);1742		wr32(hw, I40E_PRTRPB_DPS(i), reg);1743	}1744 1745	/* Write Shared Pool Size per port */1746	new_val = new_pb_cfg->shared_pool_size;1747	reg = rd32(hw, I40E_PRTRPB_SPS);1748	reg &= ~I40E_PRTRPB_SPS_SPS_MASK;1749	reg |= FIELD_PREP(I40E_PRTRPB_SPS_SPS_MASK, new_val);1750	wr32(hw, I40E_PRTRPB_SPS, reg);1751 1752	/* Program the shared pool low water mark per port if increasing */1753	old_val = old_pb_cfg->shared_pool_low_wm;1754	new_val = new_pb_cfg->shared_pool_low_wm;1755	if (new_val > old_val) {1756		reg = rd32(hw, I40E_PRTRPB_SLW);1757		reg &= ~I40E_PRTRPB_SLW_SLW_MASK;1758		reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val);1759		wr32(hw, I40E_PRTRPB_SLW, reg);1760	}1761 1762	/* Program the shared pool low threshold and tc pool1763	 * low water mark per TC that are increasing.1764	 */1765	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1766		old_val = old_pb_cfg->shared_pool_low_thresh[i];1767		new_val = new_pb_cfg->shared_pool_low_thresh[i];1768		if (new_val > old_val) {1769			reg = rd32(hw, I40E_PRTRPB_SLT(i));1770			reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;1771			reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK,1772					  new_val);1773			wr32(hw, I40E_PRTRPB_SLT(i), reg);1774		}1775 1776		old_val = old_pb_cfg->tc_pool_low_wm[i];1777		new_val = new_pb_cfg->tc_pool_low_wm[i];1778		if (new_val > old_val) {1779			reg = rd32(hw, I40E_PRTRPB_DLW(i));1780			reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;1781			reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK,1782					  new_val);1783			wr32(hw, I40E_PRTRPB_DLW(i), reg);1784		}1785	}1786 1787	/* Program the shared pool high water mark per port if increasing */1788	old_val = old_pb_cfg->shared_pool_high_wm;1789	new_val = new_pb_cfg->shared_pool_high_wm;1790	if (new_val > old_val) {1791		reg = rd32(hw, I40E_PRTRPB_SHW);1792		reg &= ~I40E_PRTRPB_SHW_SHW_MASK;1793		reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val);1794		wr32(hw, I40E_PRTRPB_SHW, reg);1795	}1796 1797	/* Program the shared pool high threshold and tc pool1798	 * high water mark per TC that are increasing.1799	 */1800	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {1801		old_val = old_pb_cfg->shared_pool_high_thresh[i];1802		new_val = new_pb_cfg->shared_pool_high_thresh[i];1803		if (new_val > old_val) {1804			reg = rd32(hw, I40E_PRTRPB_SHT(i));1805			reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;1806			reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK,1807					  new_val);1808			wr32(hw, I40E_PRTRPB_SHT(i), reg);1809		}1810 1811		old_val = old_pb_cfg->tc_pool_high_wm[i];1812		new_val = new_pb_cfg->tc_pool_high_wm[i];1813		if (new_val > old_val) {1814			reg = rd32(hw, I40E_PRTRPB_DHW(i));1815			reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;1816			reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK,1817					  new_val);1818			wr32(hw, I40E_PRTRPB_DHW(i), reg);1819		}1820	}1821}1822 1823/**1824 * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM1825 * @hw: pointer to the HW structure1826 * @lldp_cfg: pointer to hold lldp configuration variables1827 * @module: address of the module pointer1828 * @word_offset: offset of LLDP configuration1829 *1830 * Reads the LLDP configuration data from NVM using passed addresses1831 **/1832static int _i40e_read_lldp_cfg(struct i40e_hw *hw,1833			       struct i40e_lldp_variables *lldp_cfg,1834			       u8 module, u32 word_offset)1835{1836	u32 address, offset = (2 * word_offset);1837	__le16 raw_mem;1838	int ret;1839	u16 mem;1840 1841	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1842	if (ret)1843		return ret;1844 1845	ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,1846			       true, NULL);1847	i40e_release_nvm(hw);1848	if (ret)1849		return ret;1850 1851	mem = le16_to_cpu(raw_mem);1852	/* Check if this pointer needs to be read in word size or 4K sector1853	 * units.1854	 */1855	if (mem & I40E_PTR_TYPE)1856		address = (0x7FFF & mem) * 4096;1857	else1858		address = (0x7FFF & mem) * 2;1859 1860	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1861	if (ret)1862		goto err_lldp_cfg;1863 1864	ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,1865			       true, NULL);1866	i40e_release_nvm(hw);1867	if (ret)1868		return ret;1869 1870	mem = le16_to_cpu(raw_mem);1871	offset = mem + word_offset;1872	offset *= 2;1873 1874	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1875	if (ret)1876		goto err_lldp_cfg;1877 1878	ret = i40e_aq_read_nvm(hw, 0, address + offset,1879			       sizeof(struct i40e_lldp_variables), lldp_cfg,1880			       true, NULL);1881	i40e_release_nvm(hw);1882 1883err_lldp_cfg:1884	return ret;1885}1886 1887/**1888 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM1889 * @hw: pointer to the HW structure1890 * @lldp_cfg: pointer to hold lldp configuration variables1891 *1892 * Reads the LLDP configuration data from NVM1893 **/1894int i40e_read_lldp_cfg(struct i40e_hw *hw,1895		       struct i40e_lldp_variables *lldp_cfg)1896{1897	int ret = 0;1898	u32 mem;1899 1900	if (!lldp_cfg)1901		return -EINVAL;1902 1903	ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1904	if (ret)1905		return ret;1906 1907	ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),1908			       &mem, true, NULL);1909	i40e_release_nvm(hw);1910	if (ret)1911		return ret;1912 1913	/* Read a bit that holds information whether we are running flat or1914	 * structured NVM image. Flat image has LLDP configuration in shadow1915	 * ram, so there is a need to pass different addresses for both cases.1916	 */1917	if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {1918		/* Flat NVM case */1919		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,1920					  I40E_SR_LLDP_CFG_PTR);1921	} else {1922		/* Good old structured NVM image */1923		ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,1924					  I40E_NVM_LLDP_CFG_PTR);1925	}1926 1927	return ret;1928}1929