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