cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ice_dcb.c (42930B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* 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_mib
     10 * @hw: pointer to the HW struct
     11 * @bridge_type: type of bridge requested
     12 * @mib_type: Local, Remote or both Local and Remote MIBs
     13 * @buf: pointer to the caller-supplied buffer to store the MIB block
     14 * @buf_size: size of the buffer (in bytes)
     15 * @local_len: length of the returned Local LLDP MIB
     16 * @remote_len: length of the returned Remote LLDP MIB
     17 * @cd: pointer to command details structure or NULL
     18 *
     19 * Requests the complete LLDP MIB (entire packet). (0x0A00)
     20 */
     21static int
     22ice_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 |= (bridge_type << ICE_AQ_LLDP_BRID_TYPE_S) &
     39		ICE_AQ_LLDP_BRID_TYPE_M;
     40
     41	desc.datalen = cpu_to_le16(buf_size);
     42
     43	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
     44	if (!status) {
     45		if (local_len)
     46			*local_len = le16_to_cpu(cmd->local_len);
     47		if (remote_len)
     48			*remote_len = le16_to_cpu(cmd->remote_len);
     49	}
     50
     51	return status;
     52}
     53
     54/**
     55 * ice_aq_cfg_lldp_mib_change
     56 * @hw: pointer to the HW struct
     57 * @ena_update: Enable or Disable event posting
     58 * @cd: pointer to command details structure or NULL
     59 *
     60 * Enable or Disable posting of an event on ARQ when LLDP MIB
     61 * associated with the interface changes (0x0A01)
     62 */
     63static int
     64ice_aq_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_update,
     65			   struct ice_sq_cd *cd)
     66{
     67	struct ice_aqc_lldp_set_mib_change *cmd;
     68	struct ice_aq_desc desc;
     69
     70	cmd = &desc.params.lldp_set_event;
     71
     72	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_mib_change);
     73
     74	if (!ena_update)
     75		cmd->command |= ICE_AQ_LLDP_MIB_UPDATE_DIS;
     76
     77	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
     78}
     79
     80/**
     81 * ice_aq_stop_lldp
     82 * @hw: pointer to the HW struct
     83 * @shutdown_lldp_agent: True if LLDP Agent needs to be Shutdown
     84 *			 False if LLDP Agent needs to be Stopped
     85 * @persist: True if Stop/Shutdown of LLDP Agent needs to be persistent across
     86 *	     reboots
     87 * @cd: pointer to command details structure or NULL
     88 *
     89 * Stop or Shutdown the embedded LLDP Agent (0x0A05)
     90 */
     91int
     92ice_aq_stop_lldp(struct ice_hw *hw, bool shutdown_lldp_agent, bool persist,
     93		 struct ice_sq_cd *cd)
     94{
     95	struct ice_aqc_lldp_stop *cmd;
     96	struct ice_aq_desc desc;
     97
     98	cmd = &desc.params.lldp_stop;
     99
    100	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_stop);
    101
    102	if (shutdown_lldp_agent)
    103		cmd->command |= ICE_AQ_LLDP_AGENT_SHUTDOWN;
    104
    105	if (persist)
    106		cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_DIS;
    107
    108	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
    109}
    110
    111/**
    112 * ice_aq_start_lldp
    113 * @hw: pointer to the HW struct
    114 * @persist: True if Start of LLDP Agent needs to be persistent across reboots
    115 * @cd: pointer to command details structure or NULL
    116 *
    117 * Start the embedded LLDP Agent on all ports. (0x0A06)
    118 */
    119int ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd)
    120{
    121	struct ice_aqc_lldp_start *cmd;
    122	struct ice_aq_desc desc;
    123
    124	cmd = &desc.params.lldp_start;
    125
    126	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start);
    127
    128	cmd->command = ICE_AQ_LLDP_AGENT_START;
    129
    130	if (persist)
    131		cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_ENA;
    132
    133	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
    134}
    135
    136/**
    137 * ice_get_dcbx_status
    138 * @hw: pointer to the HW struct
    139 *
    140 * Get the DCBX status from the Firmware
    141 */
    142static u8 ice_get_dcbx_status(struct ice_hw *hw)
    143{
    144	u32 reg;
    145
    146	reg = rd32(hw, PRTDCB_GENS);
    147	return (u8)((reg & PRTDCB_GENS_DCBX_STATUS_M) >>
    148		    PRTDCB_GENS_DCBX_STATUS_S);
    149}
    150
    151/**
    152 * ice_parse_ieee_ets_common_tlv
    153 * @buf: Data buffer to be parsed for ETS CFG/REC data
    154 * @ets_cfg: Container to store parsed data
    155 *
    156 * Parses the common data of IEEE 802.1Qaz ETS CFG/REC TLV
    157 */
    158static void
    159ice_parse_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)
    160{
    161	u8 offset = 0;
    162	int i;
    163
    164	/* Priority Assignment Table (4 octets)
    165	 * Octets:|    1    |    2    |    3    |    4    |
    166	 *        -----------------------------------------
    167	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
    168	 *        -----------------------------------------
    169	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
    170	 *        -----------------------------------------
    171	 */
    172	for (i = 0; i < 4; i++) {
    173		ets_cfg->prio_table[i * 2] =
    174			((buf[offset] & ICE_IEEE_ETS_PRIO_1_M) >>
    175			 ICE_IEEE_ETS_PRIO_1_S);
    176		ets_cfg->prio_table[i * 2 + 1] =
    177			((buf[offset] & ICE_IEEE_ETS_PRIO_0_M) >>
    178			 ICE_IEEE_ETS_PRIO_0_S);
    179		offset++;
    180	}
    181
    182	/* TC Bandwidth Table (8 octets)
    183	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    184	 *        ---------------------------------
    185	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
    186	 *        ---------------------------------
    187	 *
    188	 * TSA Assignment Table (8 octets)
    189	 * Octets:| 9 | 10| 11| 12| 13| 14| 15| 16|
    190	 *        ---------------------------------
    191	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
    192	 *        ---------------------------------
    193	 */
    194	ice_for_each_traffic_class(i) {
    195		ets_cfg->tcbwtable[i] = buf[offset];
    196		ets_cfg->tsatable[i] = buf[ICE_MAX_TRAFFIC_CLASS + offset++];
    197	}
    198}
    199
    200/**
    201 * ice_parse_ieee_etscfg_tlv
    202 * @tlv: IEEE 802.1Qaz ETS CFG TLV
    203 * @dcbcfg: Local store to update ETS CFG data
    204 *
    205 * Parses IEEE 802.1Qaz ETS CFG TLV
    206 */
    207static void
    208ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv *tlv,
    209			  struct ice_dcbx_cfg *dcbcfg)
    210{
    211	struct ice_dcb_ets_cfg *etscfg;
    212	u8 *buf = tlv->tlvinfo;
    213
    214	/* First Octet post subtype
    215	 * --------------------------
    216	 * |will-|CBS  | Re-  | Max |
    217	 * |ing  |     |served| TCs |
    218	 * --------------------------
    219	 * |1bit | 1bit|3 bits|3bits|
    220	 */
    221	etscfg = &dcbcfg->etscfg;
    222	etscfg->willing = ((buf[0] & ICE_IEEE_ETS_WILLING_M) >>
    223			   ICE_IEEE_ETS_WILLING_S);
    224	etscfg->cbs = ((buf[0] & ICE_IEEE_ETS_CBS_M) >> ICE_IEEE_ETS_CBS_S);
    225	etscfg->maxtcs = ((buf[0] & ICE_IEEE_ETS_MAXTC_M) >>
    226			  ICE_IEEE_ETS_MAXTC_S);
    227
    228	/* Begin parsing at Priority Assignment Table (offset 1 in buf) */
    229	ice_parse_ieee_ets_common_tlv(&buf[1], etscfg);
    230}
    231
    232/**
    233 * ice_parse_ieee_etsrec_tlv
    234 * @tlv: IEEE 802.1Qaz ETS REC TLV
    235 * @dcbcfg: Local store to update ETS REC data
    236 *
    237 * Parses IEEE 802.1Qaz ETS REC TLV
    238 */
    239static void
    240ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,
    241			  struct ice_dcbx_cfg *dcbcfg)
    242{
    243	u8 *buf = tlv->tlvinfo;
    244
    245	/* Begin parsing at Priority Assignment Table (offset 1 in buf) */
    246	ice_parse_ieee_ets_common_tlv(&buf[1], &dcbcfg->etsrec);
    247}
    248
    249/**
    250 * ice_parse_ieee_pfccfg_tlv
    251 * @tlv: IEEE 802.1Qaz PFC CFG TLV
    252 * @dcbcfg: Local store to update PFC CFG data
    253 *
    254 * Parses IEEE 802.1Qaz PFC CFG TLV
    255 */
    256static void
    257ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv *tlv,
    258			  struct ice_dcbx_cfg *dcbcfg)
    259{
    260	u8 *buf = tlv->tlvinfo;
    261
    262	/* ----------------------------------------
    263	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
    264	 * |ing  |     |served| cap |              |
    265	 * -----------------------------------------
    266	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
    267	 */
    268	dcbcfg->pfc.willing = ((buf[0] & ICE_IEEE_PFC_WILLING_M) >>
    269			       ICE_IEEE_PFC_WILLING_S);
    270	dcbcfg->pfc.mbc = ((buf[0] & ICE_IEEE_PFC_MBC_M) >> ICE_IEEE_PFC_MBC_S);
    271	dcbcfg->pfc.pfccap = ((buf[0] & ICE_IEEE_PFC_CAP_M) >>
    272			      ICE_IEEE_PFC_CAP_S);
    273	dcbcfg->pfc.pfcena = buf[1];
    274}
    275
    276/**
    277 * ice_parse_ieee_app_tlv
    278 * @tlv: IEEE 802.1Qaz APP TLV
    279 * @dcbcfg: Local store to update APP PRIO data
    280 *
    281 * Parses IEEE 802.1Qaz APP PRIO TLV
    282 */
    283static void
    284ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv *tlv,
    285		       struct ice_dcbx_cfg *dcbcfg)
    286{
    287	u16 offset = 0;
    288	u16 typelen;
    289	int i = 0;
    290	u16 len;
    291	u8 *buf;
    292
    293	typelen = ntohs(tlv->typelen);
    294	len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
    295	buf = tlv->tlvinfo;
    296
    297	/* Removing sizeof(ouisubtype) and reserved byte from len.
    298	 * Remaining len div 3 is number of APP TLVs.
    299	 */
    300	len -= (sizeof(tlv->ouisubtype) + 1);
    301
    302	/* Move offset to App Priority Table */
    303	offset++;
    304
    305	/* Application Priority Table (3 octets)
    306	 * Octets:|         1          |    2    |    3    |
    307	 *        -----------------------------------------
    308	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
    309	 *        -----------------------------------------
    310	 *   Bits:|23    21|20 19|18 16|15                0|
    311	 *        -----------------------------------------
    312	 */
    313	while (offset < len) {
    314		dcbcfg->app[i].priority = ((buf[offset] &
    315					    ICE_IEEE_APP_PRIO_M) >>
    316					   ICE_IEEE_APP_PRIO_S);
    317		dcbcfg->app[i].selector = ((buf[offset] &
    318					    ICE_IEEE_APP_SEL_M) >>
    319					   ICE_IEEE_APP_SEL_S);
    320		dcbcfg->app[i].prot_id = (buf[offset + 1] << 0x8) |
    321			buf[offset + 2];
    322		/* Move to next app */
    323		offset += 3;
    324		i++;
    325		if (i >= ICE_DCBX_MAX_APPS)
    326			break;
    327	}
    328
    329	dcbcfg->numapps = i;
    330}
    331
    332/**
    333 * ice_parse_ieee_tlv
    334 * @tlv: IEEE 802.1Qaz TLV
    335 * @dcbcfg: Local store to update ETS REC data
    336 *
    337 * Get the TLV subtype and send it to parsing function
    338 * based on the subtype value
    339 */
    340static void
    341ice_parse_ieee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
    342{
    343	u32 ouisubtype;
    344	u8 subtype;
    345
    346	ouisubtype = ntohl(tlv->ouisubtype);
    347	subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >>
    348		       ICE_LLDP_TLV_SUBTYPE_S);
    349	switch (subtype) {
    350	case ICE_IEEE_SUBTYPE_ETS_CFG:
    351		ice_parse_ieee_etscfg_tlv(tlv, dcbcfg);
    352		break;
    353	case ICE_IEEE_SUBTYPE_ETS_REC:
    354		ice_parse_ieee_etsrec_tlv(tlv, dcbcfg);
    355		break;
    356	case ICE_IEEE_SUBTYPE_PFC_CFG:
    357		ice_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
    358		break;
    359	case ICE_IEEE_SUBTYPE_APP_PRI:
    360		ice_parse_ieee_app_tlv(tlv, dcbcfg);
    361		break;
    362	default:
    363		break;
    364	}
    365}
    366
    367/**
    368 * ice_parse_cee_pgcfg_tlv
    369 * @tlv: CEE DCBX PG CFG TLV
    370 * @dcbcfg: Local store to update ETS CFG data
    371 *
    372 * Parses CEE DCBX PG CFG TLV
    373 */
    374static void
    375ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv *tlv,
    376			struct ice_dcbx_cfg *dcbcfg)
    377{
    378	struct ice_dcb_ets_cfg *etscfg;
    379	u8 *buf = tlv->tlvinfo;
    380	u16 offset = 0;
    381	int i;
    382
    383	etscfg = &dcbcfg->etscfg;
    384
    385	if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)
    386		etscfg->willing = 1;
    387
    388	etscfg->cbs = 0;
    389	/* Priority Group Table (4 octets)
    390	 * Octets:|    1    |    2    |    3    |    4    |
    391	 *        -----------------------------------------
    392	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
    393	 *        -----------------------------------------
    394	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
    395	 *        -----------------------------------------
    396	 */
    397	for (i = 0; i < 4; i++) {
    398		etscfg->prio_table[i * 2] =
    399			((buf[offset] & ICE_CEE_PGID_PRIO_1_M) >>
    400			 ICE_CEE_PGID_PRIO_1_S);
    401		etscfg->prio_table[i * 2 + 1] =
    402			((buf[offset] & ICE_CEE_PGID_PRIO_0_M) >>
    403			 ICE_CEE_PGID_PRIO_0_S);
    404		offset++;
    405	}
    406
    407	/* PG Percentage Table (8 octets)
    408	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    409	 *        ---------------------------------
    410	 *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
    411	 *        ---------------------------------
    412	 */
    413	ice_for_each_traffic_class(i) {
    414		etscfg->tcbwtable[i] = buf[offset++];
    415
    416		if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT)
    417			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;
    418		else
    419			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
    420	}
    421
    422	/* Number of TCs supported (1 octet) */
    423	etscfg->maxtcs = buf[offset];
    424}
    425
    426/**
    427 * ice_parse_cee_pfccfg_tlv
    428 * @tlv: CEE DCBX PFC CFG TLV
    429 * @dcbcfg: Local store to update PFC CFG data
    430 *
    431 * Parses CEE DCBX PFC CFG TLV
    432 */
    433static void
    434ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv,
    435			 struct ice_dcbx_cfg *dcbcfg)
    436{
    437	u8 *buf = tlv->tlvinfo;
    438
    439	if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)
    440		dcbcfg->pfc.willing = 1;
    441
    442	/* ------------------------
    443	 * | PFC Enable | PFC TCs |
    444	 * ------------------------
    445	 * | 1 octet    | 1 octet |
    446	 */
    447	dcbcfg->pfc.pfcena = buf[0];
    448	dcbcfg->pfc.pfccap = buf[1];
    449}
    450
    451/**
    452 * ice_parse_cee_app_tlv
    453 * @tlv: CEE DCBX APP TLV
    454 * @dcbcfg: Local store to update APP PRIO data
    455 *
    456 * Parses CEE DCBX APP PRIO TLV
    457 */
    458static void
    459ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
    460{
    461	u16 len, typelen, offset = 0;
    462	struct ice_cee_app_prio *app;
    463	u8 i;
    464
    465	typelen = ntohs(tlv->hdr.typelen);
    466	len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
    467
    468	dcbcfg->numapps = len / sizeof(*app);
    469	if (!dcbcfg->numapps)
    470		return;
    471	if (dcbcfg->numapps > ICE_DCBX_MAX_APPS)
    472		dcbcfg->numapps = ICE_DCBX_MAX_APPS;
    473
    474	for (i = 0; i < dcbcfg->numapps; i++) {
    475		u8 up, selector;
    476
    477		app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset);
    478		for (up = 0; up < ICE_MAX_USER_PRIORITY; up++)
    479			if (app->prio_map & BIT(up))
    480				break;
    481
    482		dcbcfg->app[i].priority = up;
    483
    484		/* Get Selector from lower 2 bits, and convert to IEEE */
    485		selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M);
    486		switch (selector) {
    487		case ICE_CEE_APP_SEL_ETHTYPE:
    488			dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE;
    489			break;
    490		case ICE_CEE_APP_SEL_TCPIP:
    491			dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP;
    492			break;
    493		default:
    494			/* Keep selector as it is for unknown types */
    495			dcbcfg->app[i].selector = selector;
    496		}
    497
    498		dcbcfg->app[i].prot_id = ntohs(app->protocol);
    499		/* Move to next app */
    500		offset += sizeof(*app);
    501	}
    502}
    503
    504/**
    505 * ice_parse_cee_tlv
    506 * @tlv: CEE DCBX TLV
    507 * @dcbcfg: Local store to update DCBX config data
    508 *
    509 * Get the TLV subtype and send it to parsing function
    510 * based on the subtype value
    511 */
    512static void
    513ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
    514{
    515	struct ice_cee_feat_tlv *sub_tlv;
    516	u8 subtype, feat_tlv_count = 0;
    517	u16 len, tlvlen, typelen;
    518	u32 ouisubtype;
    519
    520	ouisubtype = ntohl(tlv->ouisubtype);
    521	subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >>
    522		       ICE_LLDP_TLV_SUBTYPE_S);
    523	/* Return if not CEE DCBX */
    524	if (subtype != ICE_CEE_DCBX_TYPE)
    525		return;
    526
    527	typelen = ntohs(tlv->typelen);
    528	tlvlen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
    529	len = sizeof(tlv->typelen) + sizeof(ouisubtype) +
    530		sizeof(struct ice_cee_ctrl_tlv);
    531	/* Return if no CEE DCBX Feature TLVs */
    532	if (tlvlen <= len)
    533		return;
    534
    535	sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len);
    536	while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) {
    537		u16 sublen;
    538
    539		typelen = ntohs(sub_tlv->hdr.typelen);
    540		sublen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
    541		subtype = (u8)((typelen & ICE_LLDP_TLV_TYPE_M) >>
    542			       ICE_LLDP_TLV_TYPE_S);
    543		switch (subtype) {
    544		case ICE_CEE_SUBTYPE_PG_CFG:
    545			ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
    546			break;
    547		case ICE_CEE_SUBTYPE_PFC_CFG:
    548			ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
    549			break;
    550		case ICE_CEE_SUBTYPE_APP_PRI:
    551			ice_parse_cee_app_tlv(sub_tlv, dcbcfg);
    552			break;
    553		default:
    554			return;	/* Invalid Sub-type return */
    555		}
    556		feat_tlv_count++;
    557		/* Move to next sub TLV */
    558		sub_tlv = (struct ice_cee_feat_tlv *)
    559			  ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) +
    560			   sublen);
    561	}
    562}
    563
    564/**
    565 * ice_parse_org_tlv
    566 * @tlv: Organization specific TLV
    567 * @dcbcfg: Local store to update ETS REC data
    568 *
    569 * Currently only IEEE 802.1Qaz TLV is supported, all others
    570 * will be returned
    571 */
    572static void
    573ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
    574{
    575	u32 ouisubtype;
    576	u32 oui;
    577
    578	ouisubtype = ntohl(tlv->ouisubtype);
    579	oui = ((ouisubtype & ICE_LLDP_TLV_OUI_M) >> ICE_LLDP_TLV_OUI_S);
    580	switch (oui) {
    581	case ICE_IEEE_8021QAZ_OUI:
    582		ice_parse_ieee_tlv(tlv, dcbcfg);
    583		break;
    584	case ICE_CEE_DCBX_OUI:
    585		ice_parse_cee_tlv(tlv, dcbcfg);
    586		break;
    587	default:
    588		break;
    589	}
    590}
    591
    592/**
    593 * ice_lldp_to_dcb_cfg
    594 * @lldpmib: LLDPDU to be parsed
    595 * @dcbcfg: store for LLDPDU data
    596 *
    597 * Parse DCB configuration from the LLDPDU
    598 */
    599static int ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
    600{
    601	struct ice_lldp_org_tlv *tlv;
    602	u16 offset = 0;
    603	int ret = 0;
    604	u16 typelen;
    605	u16 type;
    606	u16 len;
    607
    608	if (!lldpmib || !dcbcfg)
    609		return -EINVAL;
    610
    611	/* set to the start of LLDPDU */
    612	lldpmib += ETH_HLEN;
    613	tlv = (struct ice_lldp_org_tlv *)lldpmib;
    614	while (1) {
    615		typelen = ntohs(tlv->typelen);
    616		type = ((typelen & ICE_LLDP_TLV_TYPE_M) >> ICE_LLDP_TLV_TYPE_S);
    617		len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
    618		offset += sizeof(typelen) + len;
    619
    620		/* END TLV or beyond LLDPDU size */
    621		if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE)
    622			break;
    623
    624		switch (type) {
    625		case ICE_TLV_TYPE_ORG:
    626			ice_parse_org_tlv(tlv, dcbcfg);
    627			break;
    628		default:
    629			break;
    630		}
    631
    632		/* Move to next TLV */
    633		tlv = (struct ice_lldp_org_tlv *)
    634		      ((char *)tlv + sizeof(tlv->typelen) + len);
    635	}
    636
    637	return ret;
    638}
    639
    640/**
    641 * ice_aq_get_dcb_cfg
    642 * @hw: pointer to the HW struct
    643 * @mib_type: MIB type for the query
    644 * @bridgetype: bridge type for the query (remote)
    645 * @dcbcfg: store for LLDPDU data
    646 *
    647 * Query DCB configuration from the firmware
    648 */
    649int
    650ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
    651		   struct ice_dcbx_cfg *dcbcfg)
    652{
    653	u8 *lldpmib;
    654	int ret;
    655
    656	/* Allocate the LLDPDU */
    657	lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);
    658	if (!lldpmib)
    659		return -ENOMEM;
    660
    661	ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib,
    662				  ICE_LLDPDU_SIZE, NULL, NULL, NULL);
    663
    664	if (!ret)
    665		/* Parse LLDP MIB to get DCB configuration */
    666		ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg);
    667
    668	devm_kfree(ice_hw_to_dev(hw), lldpmib);
    669
    670	return ret;
    671}
    672
    673/**
    674 * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW
    675 * @hw: pointer to the HW struct
    676 * @start_dcbx_agent: True if DCBX Agent needs to be started
    677 *		      False if DCBX Agent needs to be stopped
    678 * @dcbx_agent_status: FW indicates back the DCBX agent status
    679 *		       True if DCBX Agent is active
    680 *		       False if DCBX Agent is stopped
    681 * @cd: pointer to command details structure or NULL
    682 *
    683 * Start/Stop the embedded dcbx Agent. In case that this wrapper function
    684 * returns 0, caller will need to check if FW returns back the same
    685 * value as stated in dcbx_agent_status, and react accordingly. (0x0A09)
    686 */
    687int
    688ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent,
    689		       bool *dcbx_agent_status, struct ice_sq_cd *cd)
    690{
    691	struct ice_aqc_lldp_stop_start_specific_agent *cmd;
    692	struct ice_aq_desc desc;
    693	u16 opcode;
    694	int status;
    695
    696	cmd = &desc.params.lldp_agent_ctrl;
    697
    698	opcode = ice_aqc_opc_lldp_stop_start_specific_agent;
    699
    700	ice_fill_dflt_direct_cmd_desc(&desc, opcode);
    701
    702	if (start_dcbx_agent)
    703		cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX;
    704
    705	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
    706
    707	*dcbx_agent_status = false;
    708
    709	if (!status &&
    710	    cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX)
    711		*dcbx_agent_status = true;
    712
    713	return status;
    714}
    715
    716/**
    717 * ice_aq_get_cee_dcb_cfg
    718 * @hw: pointer to the HW struct
    719 * @buff: response buffer that stores CEE operational configuration
    720 * @cd: pointer to command details structure or NULL
    721 *
    722 * Get CEE DCBX mode operational configuration from firmware (0x0A07)
    723 */
    724static int
    725ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,
    726		       struct ice_aqc_get_cee_dcb_cfg_resp *buff,
    727		       struct ice_sq_cd *cd)
    728{
    729	struct ice_aq_desc desc;
    730
    731	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg);
    732
    733	return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd);
    734}
    735
    736/**
    737 * ice_aq_set_pfc_mode - Set PFC mode
    738 * @hw: pointer to the HW struct
    739 * @pfc_mode: value of PFC mode to set
    740 * @cd: pointer to command details structure or NULL
    741 *
    742 * This AQ call configures the PFC mode to DSCP-based PFC mode or
    743 * VLAN-based PFC (0x0303)
    744 */
    745int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd)
    746{
    747	struct ice_aqc_set_query_pfc_mode *cmd;
    748	struct ice_aq_desc desc;
    749	int status;
    750
    751	if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC)
    752		return -EINVAL;
    753
    754	cmd = &desc.params.set_query_pfc_mode;
    755
    756	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode);
    757
    758	cmd->pfc_mode = pfc_mode;
    759
    760	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
    761	if (status)
    762		return status;
    763
    764	/* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is
    765	 * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has
    766	 * been executed, check if cmd->pfc_mode is what was requested. If not,
    767	 * return an error.
    768	 */
    769	if (cmd->pfc_mode != pfc_mode)
    770		return -EOPNOTSUPP;
    771
    772	return 0;
    773}
    774
    775/**
    776 * ice_cee_to_dcb_cfg
    777 * @cee_cfg: pointer to CEE configuration struct
    778 * @pi: port information structure
    779 *
    780 * Convert CEE configuration from firmware to DCB configuration
    781 */
    782static void
    783ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,
    784		   struct ice_port_info *pi)
    785{
    786	u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
    787	u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift, j;
    788	u8 i, err, sync, oper, app_index, ice_app_sel_type;
    789	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
    790	u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift;
    791	struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg;
    792	u16 ice_app_prot_id_type;
    793
    794	dcbcfg = &pi->qos_cfg.local_dcbx_cfg;
    795	dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE;
    796	dcbcfg->tlv_status = tlv_status;
    797
    798	/* CEE PG data */
    799	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
    800
    801	/* Note that the FW creates the oper_prio_tc nibbles reversed
    802	 * from those in the CEE Priority Group sub-TLV.
    803	 */
    804	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {
    805		dcbcfg->etscfg.prio_table[i * 2] =
    806			((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_0_M) >>
    807			 ICE_CEE_PGID_PRIO_0_S);
    808		dcbcfg->etscfg.prio_table[i * 2 + 1] =
    809			((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_1_M) >>
    810			 ICE_CEE_PGID_PRIO_1_S);
    811	}
    812
    813	ice_for_each_traffic_class(i) {
    814		dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
    815
    816		if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) {
    817			/* Map it to next empty TC */
    818			dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1;
    819			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;
    820		} else {
    821			dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
    822		}
    823	}
    824
    825	/* CEE PFC data */
    826	dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en;
    827	dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS;
    828
    829	/* CEE APP TLV data */
    830	if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)
    831		cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg;
    832	else
    833		cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg;
    834
    835	app_index = 0;
    836	for (i = 0; i < 3; i++) {
    837		if (i == 0) {
    838			/* FCoE APP */
    839			ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M;
    840			ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S;
    841			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M;
    842			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S;
    843			ice_app_sel_type = ICE_APP_SEL_ETHTYPE;
    844			ice_app_prot_id_type = ETH_P_FCOE;
    845		} else if (i == 1) {
    846			/* iSCSI APP */
    847			ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M;
    848			ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S;
    849			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M;
    850			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S;
    851			ice_app_sel_type = ICE_APP_SEL_TCPIP;
    852			ice_app_prot_id_type = ISCSI_LISTEN_PORT;
    853
    854			for (j = 0; j < cmp_dcbcfg->numapps; j++) {
    855				u16 prot_id = cmp_dcbcfg->app[j].prot_id;
    856				u8 sel = cmp_dcbcfg->app[j].selector;
    857
    858				if  (sel == ICE_APP_SEL_TCPIP &&
    859				     (prot_id == ISCSI_LISTEN_PORT ||
    860				      prot_id == ICE_APP_PROT_ID_ISCSI_860)) {
    861					ice_app_prot_id_type = prot_id;
    862					break;
    863				}
    864			}
    865		} else {
    866			/* FIP APP */
    867			ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M;
    868			ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S;
    869			ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M;
    870			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S;
    871			ice_app_sel_type = ICE_APP_SEL_ETHTYPE;
    872			ice_app_prot_id_type = ETH_P_FIP;
    873		}
    874
    875		status = (tlv_status & ice_aqc_cee_status_mask) >>
    876			 ice_aqc_cee_status_shift;
    877		err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0;
    878		sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0;
    879		oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0;
    880		/* Add FCoE/iSCSI/FIP APP if Error is False and
    881		 * Oper/Sync is True
    882		 */
    883		if (!err && sync && oper) {
    884			dcbcfg->app[app_index].priority =
    885				(app_prio & ice_aqc_cee_app_mask) >>
    886				ice_aqc_cee_app_shift;
    887			dcbcfg->app[app_index].selector = ice_app_sel_type;
    888			dcbcfg->app[app_index].prot_id = ice_app_prot_id_type;
    889			app_index++;
    890		}
    891	}
    892
    893	dcbcfg->numapps = app_index;
    894}
    895
    896/**
    897 * ice_get_ieee_or_cee_dcb_cfg
    898 * @pi: port information structure
    899 * @dcbx_mode: mode of DCBX (IEEE or CEE)
    900 *
    901 * Get IEEE or CEE mode DCB configuration from the Firmware
    902 */
    903static int ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode)
    904{
    905	struct ice_dcbx_cfg *dcbx_cfg = NULL;
    906	int ret;
    907
    908	if (!pi)
    909		return -EINVAL;
    910
    911	if (dcbx_mode == ICE_DCBX_MODE_IEEE)
    912		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
    913	else if (dcbx_mode == ICE_DCBX_MODE_CEE)
    914		dcbx_cfg = &pi->qos_cfg.desired_dcbx_cfg;
    915
    916	/* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE
    917	 * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE
    918	 */
    919	ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL,
    920				 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);
    921	if (ret)
    922		goto out;
    923
    924	/* Get Remote DCB Config */
    925	dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg;
    926	ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
    927				 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);
    928	/* Don't treat ENOENT as an error for Remote MIBs */
    929	if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
    930		ret = 0;
    931
    932out:
    933	return ret;
    934}
    935
    936/**
    937 * ice_get_dcb_cfg
    938 * @pi: port information structure
    939 *
    940 * Get DCB configuration from the Firmware
    941 */
    942int ice_get_dcb_cfg(struct ice_port_info *pi)
    943{
    944	struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg;
    945	struct ice_dcbx_cfg *dcbx_cfg;
    946	int ret;
    947
    948	if (!pi)
    949		return -EINVAL;
    950
    951	ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL);
    952	if (!ret) {
    953		/* CEE mode */
    954		ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE);
    955		ice_cee_to_dcb_cfg(&cee_cfg, pi);
    956	} else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) {
    957		/* CEE mode not enabled try querying IEEE data */
    958		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
    959		dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE;
    960		ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE);
    961	}
    962
    963	return ret;
    964}
    965
    966/**
    967 * ice_init_dcb
    968 * @hw: pointer to the HW struct
    969 * @enable_mib_change: enable MIB change event
    970 *
    971 * Update DCB configuration from the Firmware
    972 */
    973int ice_init_dcb(struct ice_hw *hw, bool enable_mib_change)
    974{
    975	struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;
    976	int ret = 0;
    977
    978	if (!hw->func_caps.common_cap.dcb)
    979		return -EOPNOTSUPP;
    980
    981	qos_cfg->is_sw_lldp = true;
    982
    983	/* Get DCBX status */
    984	qos_cfg->dcbx_status = ice_get_dcbx_status(hw);
    985
    986	if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DONE ||
    987	    qos_cfg->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS ||
    988	    qos_cfg->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) {
    989		/* Get current DCBX configuration */
    990		ret = ice_get_dcb_cfg(hw->port_info);
    991		if (ret)
    992			return ret;
    993		qos_cfg->is_sw_lldp = false;
    994	} else if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) {
    995		return -EBUSY;
    996	}
    997
    998	/* Configure the LLDP MIB change event */
    999	if (enable_mib_change) {
   1000		ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL);
   1001		if (ret)
   1002			qos_cfg->is_sw_lldp = true;
   1003	}
   1004
   1005	return ret;
   1006}
   1007
   1008/**
   1009 * ice_cfg_lldp_mib_change
   1010 * @hw: pointer to the HW struct
   1011 * @ena_mib: enable/disable MIB change event
   1012 *
   1013 * Configure (disable/enable) MIB
   1014 */
   1015int ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib)
   1016{
   1017	struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;
   1018	int ret;
   1019
   1020	if (!hw->func_caps.common_cap.dcb)
   1021		return -EOPNOTSUPP;
   1022
   1023	/* Get DCBX status */
   1024	qos_cfg->dcbx_status = ice_get_dcbx_status(hw);
   1025
   1026	if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS)
   1027		return -EBUSY;
   1028
   1029	ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL);
   1030	if (!ret)
   1031		qos_cfg->is_sw_lldp = !ena_mib;
   1032
   1033	return ret;
   1034}
   1035
   1036/**
   1037 * ice_add_ieee_ets_common_tlv
   1038 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data
   1039 * @ets_cfg: Container for ice_dcb_ets_cfg data
   1040 *
   1041 * Populate the TLV buffer with ice_dcb_ets_cfg data
   1042 */
   1043static void
   1044ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)
   1045{
   1046	u8 priority0, priority1;
   1047	u8 offset = 0;
   1048	int i;
   1049
   1050	/* Priority Assignment Table (4 octets)
   1051	 * Octets:|    1    |    2    |    3    |    4    |
   1052	 *        -----------------------------------------
   1053	 *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
   1054	 *        -----------------------------------------
   1055	 *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
   1056	 *        -----------------------------------------
   1057	 */
   1058	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {
   1059		priority0 = ets_cfg->prio_table[i * 2] & 0xF;
   1060		priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF;
   1061		buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1;
   1062		offset++;
   1063	}
   1064
   1065	/* TC Bandwidth Table (8 octets)
   1066	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
   1067	 *        ---------------------------------
   1068	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
   1069	 *        ---------------------------------
   1070	 *
   1071	 * TSA Assignment Table (8 octets)
   1072	 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
   1073	 *        ---------------------------------
   1074	 *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
   1075	 *        ---------------------------------
   1076	 */
   1077	ice_for_each_traffic_class(i) {
   1078		buf[offset] = ets_cfg->tcbwtable[i];
   1079		buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i];
   1080		offset++;
   1081	}
   1082}
   1083
   1084/**
   1085 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
   1086 * @tlv: Fill the ETS config data in IEEE format
   1087 * @dcbcfg: Local store which holds the DCB Config
   1088 *
   1089 * Prepare IEEE 802.1Qaz ETS CFG TLV
   1090 */
   1091static void
   1092ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
   1093{
   1094	struct ice_dcb_ets_cfg *etscfg;
   1095	u8 *buf = tlv->tlvinfo;
   1096	u8 maxtcwilling = 0;
   1097	u32 ouisubtype;
   1098	u16 typelen;
   1099
   1100	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1101		   ICE_IEEE_ETS_TLV_LEN);
   1102	tlv->typelen = htons(typelen);
   1103
   1104	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
   1105		      ICE_IEEE_SUBTYPE_ETS_CFG);
   1106	tlv->ouisubtype = htonl(ouisubtype);
   1107
   1108	/* First Octet post subtype
   1109	 * --------------------------
   1110	 * |will-|CBS  | Re-  | Max |
   1111	 * |ing  |     |served| TCs |
   1112	 * --------------------------
   1113	 * |1bit | 1bit|3 bits|3bits|
   1114	 */
   1115	etscfg = &dcbcfg->etscfg;
   1116	if (etscfg->willing)
   1117		maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S);
   1118	maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
   1119	buf[0] = maxtcwilling;
   1120
   1121	/* Begin adding at Priority Assignment Table (offset 1 in buf) */
   1122	ice_add_ieee_ets_common_tlv(&buf[1], etscfg);
   1123}
   1124
   1125/**
   1126 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
   1127 * @tlv: Fill ETS Recommended TLV in IEEE format
   1128 * @dcbcfg: Local store which holds the DCB Config
   1129 *
   1130 * Prepare IEEE 802.1Qaz ETS REC TLV
   1131 */
   1132static void
   1133ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,
   1134			struct ice_dcbx_cfg *dcbcfg)
   1135{
   1136	struct ice_dcb_ets_cfg *etsrec;
   1137	u8 *buf = tlv->tlvinfo;
   1138	u32 ouisubtype;
   1139	u16 typelen;
   1140
   1141	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1142		   ICE_IEEE_ETS_TLV_LEN);
   1143	tlv->typelen = htons(typelen);
   1144
   1145	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
   1146		      ICE_IEEE_SUBTYPE_ETS_REC);
   1147	tlv->ouisubtype = htonl(ouisubtype);
   1148
   1149	etsrec = &dcbcfg->etsrec;
   1150
   1151	/* First Octet is reserved */
   1152	/* Begin adding at Priority Assignment Table (offset 1 in buf) */
   1153	ice_add_ieee_ets_common_tlv(&buf[1], etsrec);
   1154}
   1155
   1156/**
   1157 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
   1158 * @tlv: Fill PFC TLV in IEEE format
   1159 * @dcbcfg: Local store which holds the PFC CFG data
   1160 *
   1161 * Prepare IEEE 802.1Qaz PFC CFG TLV
   1162 */
   1163static void
   1164ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
   1165{
   1166	u8 *buf = tlv->tlvinfo;
   1167	u32 ouisubtype;
   1168	u16 typelen;
   1169
   1170	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1171		   ICE_IEEE_PFC_TLV_LEN);
   1172	tlv->typelen = htons(typelen);
   1173
   1174	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
   1175		      ICE_IEEE_SUBTYPE_PFC_CFG);
   1176	tlv->ouisubtype = htonl(ouisubtype);
   1177
   1178	/* ----------------------------------------
   1179	 * |will-|MBC  | Re-  | PFC |  PFC Enable  |
   1180	 * |ing  |     |served| cap |              |
   1181	 * -----------------------------------------
   1182	 * |1bit | 1bit|2 bits|4bits| 1 octet      |
   1183	 */
   1184	if (dcbcfg->pfc.willing)
   1185		buf[0] = BIT(ICE_IEEE_PFC_WILLING_S);
   1186
   1187	if (dcbcfg->pfc.mbc)
   1188		buf[0] |= BIT(ICE_IEEE_PFC_MBC_S);
   1189
   1190	buf[0] |= dcbcfg->pfc.pfccap & 0xF;
   1191	buf[1] = dcbcfg->pfc.pfcena;
   1192}
   1193
   1194/**
   1195 * ice_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format
   1196 * @tlv: Fill APP TLV in IEEE format
   1197 * @dcbcfg: Local store which holds the APP CFG data
   1198 *
   1199 * Prepare IEEE 802.1Qaz APP CFG TLV
   1200 */
   1201static void
   1202ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,
   1203			 struct ice_dcbx_cfg *dcbcfg)
   1204{
   1205	u16 typelen, len, offset = 0;
   1206	u8 priority, selector, i = 0;
   1207	u8 *buf = tlv->tlvinfo;
   1208	u32 ouisubtype;
   1209
   1210	/* No APP TLVs then just return */
   1211	if (dcbcfg->numapps == 0)
   1212		return;
   1213	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
   1214		      ICE_IEEE_SUBTYPE_APP_PRI);
   1215	tlv->ouisubtype = htonl(ouisubtype);
   1216
   1217	/* Move offset to App Priority Table */
   1218	offset++;
   1219	/* Application Priority Table (3 octets)
   1220	 * Octets:|         1          |    2    |    3    |
   1221	 *        -----------------------------------------
   1222	 *        |Priority|Rsrvd| Sel |    Protocol ID    |
   1223	 *        -----------------------------------------
   1224	 *   Bits:|23    21|20 19|18 16|15                0|
   1225	 *        -----------------------------------------
   1226	 */
   1227	while (i < dcbcfg->numapps) {
   1228		priority = dcbcfg->app[i].priority & 0x7;
   1229		selector = dcbcfg->app[i].selector & 0x7;
   1230		buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector;
   1231		buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF;
   1232		buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF;
   1233		/* Move to next app */
   1234		offset += 3;
   1235		i++;
   1236		if (i >= ICE_DCBX_MAX_APPS)
   1237			break;
   1238	}
   1239	/* len includes size of ouisubtype + 1 reserved + 3*numapps */
   1240	len = sizeof(tlv->ouisubtype) + 1 + (i * 3);
   1241	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF));
   1242	tlv->typelen = htons(typelen);
   1243}
   1244
   1245/**
   1246 * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV
   1247 * @tlv: location to build the TLV data
   1248 * @dcbcfg: location of data to convert to TLV
   1249 */
   1250static void
   1251ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
   1252{
   1253	u8 *buf = tlv->tlvinfo;
   1254	u32 ouisubtype;
   1255	u16 typelen;
   1256	int i;
   1257
   1258	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1259		   ICE_DSCP_UP_TLV_LEN);
   1260	tlv->typelen = htons(typelen);
   1261
   1262	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
   1263			   ICE_DSCP_SUBTYPE_DSCP2UP);
   1264	tlv->ouisubtype = htonl(ouisubtype);
   1265
   1266	/* bytes 0 - 63 - IPv4 DSCP2UP LUT */
   1267	for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {
   1268		/* IPv4 mapping */
   1269		buf[i] = dcbcfg->dscp_map[i];
   1270		/* IPv6 mapping */
   1271		buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];
   1272	}
   1273
   1274	/* byte 64 - IPv4 untagged traffic */
   1275	buf[i] = 0;
   1276
   1277	/* byte 144 - IPv6 untagged traffic */
   1278	buf[i + ICE_DSCP_IPV6_OFFSET] = 0;
   1279}
   1280
   1281#define ICE_BYTES_PER_TC	8
   1282/**
   1283 * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV
   1284 * @tlv: location to build the TLV data
   1285 */
   1286static void
   1287ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)
   1288{
   1289	u8 *buf = tlv->tlvinfo;
   1290	u32 ouisubtype;
   1291	u16 typelen;
   1292
   1293	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1294		   ICE_DSCP_ENF_TLV_LEN);
   1295	tlv->typelen = htons(typelen);
   1296
   1297	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
   1298			   ICE_DSCP_SUBTYPE_ENFORCE);
   1299	tlv->ouisubtype = htonl(ouisubtype);
   1300
   1301	/* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */
   1302	memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));
   1303}
   1304
   1305/**
   1306 * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV
   1307 * @tlv: location to build the TLV data
   1308 * @dcbcfg: location of the data to convert to TLV
   1309 */
   1310static void
   1311ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,
   1312		       struct ice_dcbx_cfg *dcbcfg)
   1313{
   1314	struct ice_dcb_ets_cfg *etscfg;
   1315	u8 *buf = tlv->tlvinfo;
   1316	u32 ouisubtype;
   1317	u8 offset = 0;
   1318	u16 typelen;
   1319	int i;
   1320
   1321	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1322		   ICE_DSCP_TC_BW_TLV_LEN);
   1323	tlv->typelen = htons(typelen);
   1324
   1325	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
   1326			   ICE_DSCP_SUBTYPE_TCBW);
   1327	tlv->ouisubtype = htonl(ouisubtype);
   1328
   1329	/* First Octect after subtype
   1330	 * ----------------------------
   1331	 * | RSV | CBS | RSV | Max TCs |
   1332	 * | 1b  | 1b  | 3b  | 3b      |
   1333	 * ----------------------------
   1334	 */
   1335	etscfg = &dcbcfg->etscfg;
   1336	buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
   1337
   1338	/* bytes 1 - 4 reserved */
   1339	offset = 5;
   1340
   1341	/* TC BW table
   1342	 * bytes 0 - 7 for TC 0 - 7
   1343	 *
   1344	 * TSA Assignment table
   1345	 * bytes 8 - 15 for TC 0 - 7
   1346	 */
   1347	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
   1348		buf[offset] = etscfg->tcbwtable[i];
   1349		buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];
   1350		offset++;
   1351	}
   1352}
   1353
   1354/**
   1355 * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV
   1356 * @tlv: Fill PFC TLV in IEEE format
   1357 * @dcbcfg: Local store which holds the PFC CFG data
   1358 */
   1359static void
   1360ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
   1361{
   1362	u8 *buf = tlv->tlvinfo;
   1363	u32 ouisubtype;
   1364	u16 typelen;
   1365
   1366	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
   1367		   ICE_DSCP_PFC_TLV_LEN);
   1368	tlv->typelen = htons(typelen);
   1369
   1370	ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
   1371			   ICE_DSCP_SUBTYPE_PFC);
   1372	tlv->ouisubtype = htonl(ouisubtype);
   1373
   1374	buf[0] = dcbcfg->pfc.pfccap & 0xF;
   1375	buf[1] = dcbcfg->pfc.pfcena & 0xF;
   1376}
   1377
   1378/**
   1379 * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs
   1380 * @tlv: Fill TLV data in IEEE format
   1381 * @dcbcfg: Local store which holds the DCB Config
   1382 * @tlvid: Type of IEEE TLV
   1383 *
   1384 * Add tlv information
   1385 */
   1386static void
   1387ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,
   1388		u16 tlvid)
   1389{
   1390	if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {
   1391		switch (tlvid) {
   1392		case ICE_IEEE_TLV_ID_ETS_CFG:
   1393			ice_add_ieee_ets_tlv(tlv, dcbcfg);
   1394			break;
   1395		case ICE_IEEE_TLV_ID_ETS_REC:
   1396			ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
   1397			break;
   1398		case ICE_IEEE_TLV_ID_PFC_CFG:
   1399			ice_add_ieee_pfc_tlv(tlv, dcbcfg);
   1400			break;
   1401		case ICE_IEEE_TLV_ID_APP_PRI:
   1402			ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
   1403			break;
   1404		default:
   1405			break;
   1406		}
   1407	} else {
   1408		/* pfc_mode == ICE_QOS_MODE_DSCP */
   1409		switch (tlvid) {
   1410		case ICE_TLV_ID_DSCP_UP:
   1411			ice_add_dscp_up_tlv(tlv, dcbcfg);
   1412			break;
   1413		case ICE_TLV_ID_DSCP_ENF:
   1414			ice_add_dscp_enf_tlv(tlv);
   1415			break;
   1416		case ICE_TLV_ID_DSCP_TC_BW:
   1417			ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);
   1418			break;
   1419		case ICE_TLV_ID_DSCP_TO_PFC:
   1420			ice_add_dscp_pfc_tlv(tlv, dcbcfg);
   1421			break;
   1422		default:
   1423			break;
   1424		}
   1425	}
   1426}
   1427
   1428/**
   1429 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format
   1430 * @lldpmib: pointer to the HW struct
   1431 * @miblen: length of LLDP MIB
   1432 * @dcbcfg: Local store which holds the DCB Config
   1433 *
   1434 * Convert the DCB configuration to MIB format
   1435 */
   1436static void
   1437ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg)
   1438{
   1439	u16 len, offset = 0, tlvid = ICE_TLV_ID_START;
   1440	struct ice_lldp_org_tlv *tlv;
   1441	u16 typelen;
   1442
   1443	tlv = (struct ice_lldp_org_tlv *)lldpmib;
   1444	while (1) {
   1445		ice_add_dcb_tlv(tlv, dcbcfg, tlvid++);
   1446		typelen = ntohs(tlv->typelen);
   1447		len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
   1448		if (len)
   1449			offset += len + 2;
   1450		/* END TLV or beyond LLDPDU size */
   1451		if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU ||
   1452		    offset > ICE_LLDPDU_SIZE)
   1453			break;
   1454		/* Move to next TLV */
   1455		if (len)
   1456			tlv = (struct ice_lldp_org_tlv *)
   1457				((char *)tlv + sizeof(tlv->typelen) + len);
   1458	}
   1459	*miblen = offset;
   1460}
   1461
   1462/**
   1463 * ice_set_dcb_cfg - Set the local LLDP MIB to FW
   1464 * @pi: port information structure
   1465 *
   1466 * Set DCB configuration to the Firmware
   1467 */
   1468int ice_set_dcb_cfg(struct ice_port_info *pi)
   1469{
   1470	u8 mib_type, *lldpmib = NULL;
   1471	struct ice_dcbx_cfg *dcbcfg;
   1472	struct ice_hw *hw;
   1473	u16 miblen;
   1474	int ret;
   1475
   1476	if (!pi)
   1477		return -EINVAL;
   1478
   1479	hw = pi->hw;
   1480
   1481	/* update the HW local config */
   1482	dcbcfg = &pi->qos_cfg.local_dcbx_cfg;
   1483	/* Allocate the LLDPDU */
   1484	lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);
   1485	if (!lldpmib)
   1486		return -ENOMEM;
   1487
   1488	mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB;
   1489	if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)
   1490		mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING;
   1491
   1492	ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg);
   1493	ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen,
   1494				  NULL);
   1495
   1496	devm_kfree(ice_hw_to_dev(hw), lldpmib);
   1497
   1498	return ret;
   1499}
   1500
   1501/**
   1502 * ice_aq_query_port_ets - query port ETS configuration
   1503 * @pi: port information structure
   1504 * @buf: pointer to buffer
   1505 * @buf_size: buffer size in bytes
   1506 * @cd: pointer to command details structure or NULL
   1507 *
   1508 * query current port ETS configuration
   1509 */
   1510static int
   1511ice_aq_query_port_ets(struct ice_port_info *pi,
   1512		      struct ice_aqc_port_ets_elem *buf, u16 buf_size,
   1513		      struct ice_sq_cd *cd)
   1514{
   1515	struct ice_aqc_query_port_ets *cmd;
   1516	struct ice_aq_desc desc;
   1517	int status;
   1518
   1519	if (!pi)
   1520		return -EINVAL;
   1521	cmd = &desc.params.port_ets;
   1522	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets);
   1523	cmd->port_teid = pi->root->info.node_teid;
   1524
   1525	status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd);
   1526	return status;
   1527}
   1528
   1529/**
   1530 * ice_update_port_tc_tree_cfg - update TC tree configuration
   1531 * @pi: port information structure
   1532 * @buf: pointer to buffer
   1533 *
   1534 * update the SW DB with the new TC changes
   1535 */
   1536static int
   1537ice_update_port_tc_tree_cfg(struct ice_port_info *pi,
   1538			    struct ice_aqc_port_ets_elem *buf)
   1539{
   1540	struct ice_sched_node *node, *tc_node;
   1541	struct ice_aqc_txsched_elem_data elem;
   1542	u32 teid1, teid2;
   1543	int status = 0;
   1544	u8 i, j;
   1545
   1546	if (!pi)
   1547		return -EINVAL;
   1548	/* suspend the missing TC nodes */
   1549	for (i = 0; i < pi->root->num_children; i++) {
   1550		teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid);
   1551		ice_for_each_traffic_class(j) {
   1552			teid2 = le32_to_cpu(buf->tc_node_teid[j]);
   1553			if (teid1 == teid2)
   1554				break;
   1555		}
   1556		if (j < ICE_MAX_TRAFFIC_CLASS)
   1557			continue;
   1558		/* TC is missing */
   1559		pi->root->children[i]->in_use = false;
   1560	}
   1561	/* add the new TC nodes */
   1562	ice_for_each_traffic_class(j) {
   1563		teid2 = le32_to_cpu(buf->tc_node_teid[j]);
   1564		if (teid2 == ICE_INVAL_TEID)
   1565			continue;
   1566		/* Is it already present in the tree ? */
   1567		for (i = 0; i < pi->root->num_children; i++) {
   1568			tc_node = pi->root->children[i];
   1569			if (!tc_node)
   1570				continue;
   1571			teid1 = le32_to_cpu(tc_node->info.node_teid);
   1572			if (teid1 == teid2) {
   1573				tc_node->tc_num = j;
   1574				tc_node->in_use = true;
   1575				break;
   1576			}
   1577		}
   1578		if (i < pi->root->num_children)
   1579			continue;
   1580		/* new TC */
   1581		status = ice_sched_query_elem(pi->hw, teid2, &elem);
   1582		if (!status)
   1583			status = ice_sched_add_node(pi, 1, &elem);
   1584		if (status)
   1585			break;
   1586		/* update the TC number */
   1587		node = ice_sched_find_node_by_teid(pi->root, teid2);
   1588		if (node)
   1589			node->tc_num = j;
   1590	}
   1591	return status;
   1592}
   1593
   1594/**
   1595 * ice_query_port_ets - query port ETS configuration
   1596 * @pi: port information structure
   1597 * @buf: pointer to buffer
   1598 * @buf_size: buffer size in bytes
   1599 * @cd: pointer to command details structure or NULL
   1600 *
   1601 * query current port ETS configuration and update the
   1602 * SW DB with the TC changes
   1603 */
   1604int
   1605ice_query_port_ets(struct ice_port_info *pi,
   1606		   struct ice_aqc_port_ets_elem *buf, u16 buf_size,
   1607		   struct ice_sq_cd *cd)
   1608{
   1609	int status;
   1610
   1611	mutex_lock(&pi->sched_lock);
   1612	status = ice_aq_query_port_ets(pi, buf, buf_size, cd);
   1613	if (!status)
   1614		status = ice_update_port_tc_tree_cfg(pi, buf);
   1615	mutex_unlock(&pi->sched_lock);
   1616	return status;
   1617}