Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2013 - 2021 Intel Corporation. */
0003 
0004 #include "i40e_adminq.h"
0005 #include "i40e_prototype.h"
0006 #include "i40e_dcb.h"
0007 
0008 /**
0009  * i40e_get_dcbx_status
0010  * @hw: pointer to the hw struct
0011  * @status: Embedded DCBX Engine Status
0012  *
0013  * Get the DCBX status from the Firmware
0014  **/
0015 i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
0016 {
0017     u32 reg;
0018 
0019     if (!status)
0020         return I40E_ERR_PARAM;
0021 
0022     reg = rd32(hw, I40E_PRTDCB_GENS);
0023     *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
0024             I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
0025 
0026     return 0;
0027 }
0028 
0029 /**
0030  * i40e_parse_ieee_etscfg_tlv
0031  * @tlv: IEEE 802.1Qaz ETS CFG TLV
0032  * @dcbcfg: Local store to update ETS CFG data
0033  *
0034  * Parses IEEE 802.1Qaz ETS CFG TLV
0035  **/
0036 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
0037                        struct i40e_dcbx_config *dcbcfg)
0038 {
0039     struct i40e_dcb_ets_config *etscfg;
0040     u8 *buf = tlv->tlvinfo;
0041     u16 offset = 0;
0042     u8 priority;
0043     int i;
0044 
0045     /* First Octet post subtype
0046      * --------------------------
0047      * |will-|CBS  | Re-  | Max |
0048      * |ing  |     |served| TCs |
0049      * --------------------------
0050      * |1bit | 1bit|3 bits|3bits|
0051      */
0052     etscfg = &dcbcfg->etscfg;
0053     etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
0054                    I40E_IEEE_ETS_WILLING_SHIFT);
0055     etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
0056                I40E_IEEE_ETS_CBS_SHIFT);
0057     etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
0058                   I40E_IEEE_ETS_MAXTC_SHIFT);
0059 
0060     /* Move offset to Priority Assignment Table */
0061     offset++;
0062 
0063     /* Priority Assignment Table (4 octets)
0064      * Octets:|    1    |    2    |    3    |    4    |
0065      *        -----------------------------------------
0066      *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
0067      *        -----------------------------------------
0068      *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
0069      *        -----------------------------------------
0070      */
0071     for (i = 0; i < 4; i++) {
0072         priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
0073                 I40E_IEEE_ETS_PRIO_1_SHIFT);
0074         etscfg->prioritytable[i * 2] =  priority;
0075         priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
0076                 I40E_IEEE_ETS_PRIO_0_SHIFT);
0077         etscfg->prioritytable[i * 2 + 1] = priority;
0078         offset++;
0079     }
0080 
0081     /* TC Bandwidth Table (8 octets)
0082      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0083      *        ---------------------------------
0084      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
0085      *        ---------------------------------
0086      */
0087     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0088         etscfg->tcbwtable[i] = buf[offset++];
0089 
0090     /* TSA Assignment Table (8 octets)
0091      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0092      *        ---------------------------------
0093      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
0094      *        ---------------------------------
0095      */
0096     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0097         etscfg->tsatable[i] = buf[offset++];
0098 }
0099 
0100 /**
0101  * i40e_parse_ieee_etsrec_tlv
0102  * @tlv: IEEE 802.1Qaz ETS REC TLV
0103  * @dcbcfg: Local store to update ETS REC data
0104  *
0105  * Parses IEEE 802.1Qaz ETS REC TLV
0106  **/
0107 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
0108                        struct i40e_dcbx_config *dcbcfg)
0109 {
0110     u8 *buf = tlv->tlvinfo;
0111     u16 offset = 0;
0112     u8 priority;
0113     int i;
0114 
0115     /* Move offset to priority table */
0116     offset++;
0117 
0118     /* Priority Assignment Table (4 octets)
0119      * Octets:|    1    |    2    |    3    |    4    |
0120      *        -----------------------------------------
0121      *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
0122      *        -----------------------------------------
0123      *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
0124      *        -----------------------------------------
0125      */
0126     for (i = 0; i < 4; i++) {
0127         priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
0128                 I40E_IEEE_ETS_PRIO_1_SHIFT);
0129         dcbcfg->etsrec.prioritytable[i*2] =  priority;
0130         priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
0131                 I40E_IEEE_ETS_PRIO_0_SHIFT);
0132         dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
0133         offset++;
0134     }
0135 
0136     /* TC Bandwidth Table (8 octets)
0137      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0138      *        ---------------------------------
0139      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
0140      *        ---------------------------------
0141      */
0142     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0143         dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
0144 
0145     /* TSA Assignment Table (8 octets)
0146      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0147      *        ---------------------------------
0148      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
0149      *        ---------------------------------
0150      */
0151     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0152         dcbcfg->etsrec.tsatable[i] = buf[offset++];
0153 }
0154 
0155 /**
0156  * i40e_parse_ieee_pfccfg_tlv
0157  * @tlv: IEEE 802.1Qaz PFC CFG TLV
0158  * @dcbcfg: Local store to update PFC CFG data
0159  *
0160  * Parses IEEE 802.1Qaz PFC CFG TLV
0161  **/
0162 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
0163                        struct i40e_dcbx_config *dcbcfg)
0164 {
0165     u8 *buf = tlv->tlvinfo;
0166 
0167     /* ----------------------------------------
0168      * |will-|MBC  | Re-  | PFC |  PFC Enable  |
0169      * |ing  |     |served| cap |              |
0170      * -----------------------------------------
0171      * |1bit | 1bit|2 bits|4bits| 1 octet      |
0172      */
0173     dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
0174                    I40E_IEEE_PFC_WILLING_SHIFT);
0175     dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
0176                    I40E_IEEE_PFC_MBC_SHIFT);
0177     dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
0178                   I40E_IEEE_PFC_CAP_SHIFT);
0179     dcbcfg->pfc.pfcenable = buf[1];
0180 }
0181 
0182 /**
0183  * i40e_parse_ieee_app_tlv
0184  * @tlv: IEEE 802.1Qaz APP TLV
0185  * @dcbcfg: Local store to update APP PRIO data
0186  *
0187  * Parses IEEE 802.1Qaz APP PRIO TLV
0188  **/
0189 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
0190                     struct i40e_dcbx_config *dcbcfg)
0191 {
0192     u16 typelength;
0193     u16 offset = 0;
0194     u16 length;
0195     int i = 0;
0196     u8 *buf;
0197 
0198     typelength = ntohs(tlv->typelength);
0199     length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
0200                I40E_LLDP_TLV_LEN_SHIFT);
0201     buf = tlv->tlvinfo;
0202 
0203     /* The App priority table starts 5 octets after TLV header */
0204     length -= (sizeof(tlv->ouisubtype) + 1);
0205 
0206     /* Move offset to App Priority Table */
0207     offset++;
0208 
0209     /* Application Priority Table (3 octets)
0210      * Octets:|         1          |    2    |    3    |
0211      *        -----------------------------------------
0212      *        |Priority|Rsrvd| Sel |    Protocol ID    |
0213      *        -----------------------------------------
0214      *   Bits:|23    21|20 19|18 16|15                0|
0215      *        -----------------------------------------
0216      */
0217     while (offset < length) {
0218         dcbcfg->app[i].priority = (u8)((buf[offset] &
0219                         I40E_IEEE_APP_PRIO_MASK) >>
0220                            I40E_IEEE_APP_PRIO_SHIFT);
0221         dcbcfg->app[i].selector = (u8)((buf[offset] &
0222                         I40E_IEEE_APP_SEL_MASK) >>
0223                            I40E_IEEE_APP_SEL_SHIFT);
0224         dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
0225                          buf[offset + 2];
0226         /* Move to next app */
0227         offset += 3;
0228         i++;
0229         if (i >= I40E_DCBX_MAX_APPS)
0230             break;
0231     }
0232 
0233     dcbcfg->numapps = i;
0234 }
0235 
0236 /**
0237  * i40e_parse_ieee_tlv
0238  * @tlv: IEEE 802.1Qaz TLV
0239  * @dcbcfg: Local store to update ETS REC data
0240  *
0241  * Get the TLV subtype and send it to parsing function
0242  * based on the subtype value
0243  **/
0244 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
0245                 struct i40e_dcbx_config *dcbcfg)
0246 {
0247     u32 ouisubtype;
0248     u8 subtype;
0249 
0250     ouisubtype = ntohl(tlv->ouisubtype);
0251     subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
0252                I40E_LLDP_TLV_SUBTYPE_SHIFT);
0253     switch (subtype) {
0254     case I40E_IEEE_SUBTYPE_ETS_CFG:
0255         i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
0256         break;
0257     case I40E_IEEE_SUBTYPE_ETS_REC:
0258         i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
0259         break;
0260     case I40E_IEEE_SUBTYPE_PFC_CFG:
0261         i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
0262         break;
0263     case I40E_IEEE_SUBTYPE_APP_PRI:
0264         i40e_parse_ieee_app_tlv(tlv, dcbcfg);
0265         break;
0266     default:
0267         break;
0268     }
0269 }
0270 
0271 /**
0272  * i40e_parse_cee_pgcfg_tlv
0273  * @tlv: CEE DCBX PG CFG TLV
0274  * @dcbcfg: Local store to update ETS CFG data
0275  *
0276  * Parses CEE DCBX PG CFG TLV
0277  **/
0278 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
0279                      struct i40e_dcbx_config *dcbcfg)
0280 {
0281     struct i40e_dcb_ets_config *etscfg;
0282     u8 *buf = tlv->tlvinfo;
0283     u16 offset = 0;
0284     u8 priority;
0285     int i;
0286 
0287     etscfg = &dcbcfg->etscfg;
0288 
0289     if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
0290         etscfg->willing = 1;
0291 
0292     etscfg->cbs = 0;
0293     /* Priority Group Table (4 octets)
0294      * Octets:|    1    |    2    |    3    |    4    |
0295      *        -----------------------------------------
0296      *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
0297      *        -----------------------------------------
0298      *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
0299      *        -----------------------------------------
0300      */
0301     for (i = 0; i < 4; i++) {
0302         priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
0303                  I40E_CEE_PGID_PRIO_1_SHIFT);
0304         etscfg->prioritytable[i * 2] =  priority;
0305         priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
0306                  I40E_CEE_PGID_PRIO_0_SHIFT);
0307         etscfg->prioritytable[i * 2 + 1] = priority;
0308         offset++;
0309     }
0310 
0311     /* PG Percentage Table (8 octets)
0312      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0313      *        ---------------------------------
0314      *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
0315      *        ---------------------------------
0316      */
0317     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0318         etscfg->tcbwtable[i] = buf[offset++];
0319 
0320     /* Number of TCs supported (1 octet) */
0321     etscfg->maxtcs = buf[offset];
0322 }
0323 
0324 /**
0325  * i40e_parse_cee_pfccfg_tlv
0326  * @tlv: CEE DCBX PFC CFG TLV
0327  * @dcbcfg: Local store to update PFC CFG data
0328  *
0329  * Parses CEE DCBX PFC CFG TLV
0330  **/
0331 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
0332                       struct i40e_dcbx_config *dcbcfg)
0333 {
0334     u8 *buf = tlv->tlvinfo;
0335 
0336     if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
0337         dcbcfg->pfc.willing = 1;
0338 
0339     /* ------------------------
0340      * | PFC Enable | PFC TCs |
0341      * ------------------------
0342      * | 1 octet    | 1 octet |
0343      */
0344     dcbcfg->pfc.pfcenable = buf[0];
0345     dcbcfg->pfc.pfccap = buf[1];
0346 }
0347 
0348 /**
0349  * i40e_parse_cee_app_tlv
0350  * @tlv: CEE DCBX APP TLV
0351  * @dcbcfg: Local store to update APP PRIO data
0352  *
0353  * Parses CEE DCBX APP PRIO TLV
0354  **/
0355 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
0356                    struct i40e_dcbx_config *dcbcfg)
0357 {
0358     u16 length, typelength, offset = 0;
0359     struct i40e_cee_app_prio *app;
0360     u8 i;
0361 
0362     typelength = ntohs(tlv->hdr.typelen);
0363     length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
0364                I40E_LLDP_TLV_LEN_SHIFT);
0365 
0366     dcbcfg->numapps = length / sizeof(*app);
0367 
0368     if (!dcbcfg->numapps)
0369         return;
0370     if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
0371         dcbcfg->numapps = I40E_DCBX_MAX_APPS;
0372 
0373     for (i = 0; i < dcbcfg->numapps; i++) {
0374         u8 up, selector;
0375 
0376         app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
0377         for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
0378             if (app->prio_map & BIT(up))
0379                 break;
0380         }
0381         dcbcfg->app[i].priority = up;
0382 
0383         /* Get Selector from lower 2 bits, and convert to IEEE */
0384         selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
0385         switch (selector) {
0386         case I40E_CEE_APP_SEL_ETHTYPE:
0387             dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
0388             break;
0389         case I40E_CEE_APP_SEL_TCPIP:
0390             dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
0391             break;
0392         default:
0393             /* Keep selector as it is for unknown types */
0394             dcbcfg->app[i].selector = selector;
0395         }
0396 
0397         dcbcfg->app[i].protocolid = ntohs(app->protocol);
0398         /* Move to next app */
0399         offset += sizeof(*app);
0400     }
0401 }
0402 
0403 /**
0404  * i40e_parse_cee_tlv
0405  * @tlv: CEE DCBX TLV
0406  * @dcbcfg: Local store to update DCBX config data
0407  *
0408  * Get the TLV subtype and send it to parsing function
0409  * based on the subtype value
0410  **/
0411 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
0412                    struct i40e_dcbx_config *dcbcfg)
0413 {
0414     u16 len, tlvlen, sublen, typelength;
0415     struct i40e_cee_feat_tlv *sub_tlv;
0416     u8 subtype, feat_tlv_count = 0;
0417     u32 ouisubtype;
0418 
0419     ouisubtype = ntohl(tlv->ouisubtype);
0420     subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
0421                I40E_LLDP_TLV_SUBTYPE_SHIFT);
0422     /* Return if not CEE DCBX */
0423     if (subtype != I40E_CEE_DCBX_TYPE)
0424         return;
0425 
0426     typelength = ntohs(tlv->typelength);
0427     tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
0428             I40E_LLDP_TLV_LEN_SHIFT);
0429     len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
0430           sizeof(struct i40e_cee_ctrl_tlv);
0431     /* Return if no CEE DCBX Feature TLVs */
0432     if (tlvlen <= len)
0433         return;
0434 
0435     sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
0436     while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
0437         typelength = ntohs(sub_tlv->hdr.typelen);
0438         sublen = (u16)((typelength &
0439                 I40E_LLDP_TLV_LEN_MASK) >>
0440                 I40E_LLDP_TLV_LEN_SHIFT);
0441         subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
0442                 I40E_LLDP_TLV_TYPE_SHIFT);
0443         switch (subtype) {
0444         case I40E_CEE_SUBTYPE_PG_CFG:
0445             i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
0446             break;
0447         case I40E_CEE_SUBTYPE_PFC_CFG:
0448             i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
0449             break;
0450         case I40E_CEE_SUBTYPE_APP_PRI:
0451             i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
0452             break;
0453         default:
0454             return; /* Invalid Sub-type return */
0455         }
0456         feat_tlv_count++;
0457         /* Move to next sub TLV */
0458         sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
0459                         sizeof(sub_tlv->hdr.typelen) +
0460                         sublen);
0461     }
0462 }
0463 
0464 /**
0465  * i40e_parse_org_tlv
0466  * @tlv: Organization specific TLV
0467  * @dcbcfg: Local store to update ETS REC data
0468  *
0469  * Currently only IEEE 802.1Qaz TLV is supported, all others
0470  * will be returned
0471  **/
0472 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
0473                    struct i40e_dcbx_config *dcbcfg)
0474 {
0475     u32 ouisubtype;
0476     u32 oui;
0477 
0478     ouisubtype = ntohl(tlv->ouisubtype);
0479     oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
0480             I40E_LLDP_TLV_OUI_SHIFT);
0481     switch (oui) {
0482     case I40E_IEEE_8021QAZ_OUI:
0483         i40e_parse_ieee_tlv(tlv, dcbcfg);
0484         break;
0485     case I40E_CEE_DCBX_OUI:
0486         i40e_parse_cee_tlv(tlv, dcbcfg);
0487         break;
0488     default:
0489         break;
0490     }
0491 }
0492 
0493 /**
0494  * i40e_lldp_to_dcb_config
0495  * @lldpmib: LLDPDU to be parsed
0496  * @dcbcfg: store for LLDPDU data
0497  *
0498  * Parse DCB configuration from the LLDPDU
0499  **/
0500 i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
0501                     struct i40e_dcbx_config *dcbcfg)
0502 {
0503     i40e_status ret = 0;
0504     struct i40e_lldp_org_tlv *tlv;
0505     u16 type;
0506     u16 length;
0507     u16 typelength;
0508     u16 offset = 0;
0509 
0510     if (!lldpmib || !dcbcfg)
0511         return I40E_ERR_PARAM;
0512 
0513     /* set to the start of LLDPDU */
0514     lldpmib += ETH_HLEN;
0515     tlv = (struct i40e_lldp_org_tlv *)lldpmib;
0516     while (1) {
0517         typelength = ntohs(tlv->typelength);
0518         type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
0519                  I40E_LLDP_TLV_TYPE_SHIFT);
0520         length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
0521                    I40E_LLDP_TLV_LEN_SHIFT);
0522         offset += sizeof(typelength) + length;
0523 
0524         /* END TLV or beyond LLDPDU size */
0525         if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
0526             break;
0527 
0528         switch (type) {
0529         case I40E_TLV_TYPE_ORG:
0530             i40e_parse_org_tlv(tlv, dcbcfg);
0531             break;
0532         default:
0533             break;
0534         }
0535 
0536         /* Move to next TLV */
0537         tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
0538                             sizeof(tlv->typelength) +
0539                             length);
0540     }
0541 
0542     return ret;
0543 }
0544 
0545 /**
0546  * i40e_aq_get_dcb_config
0547  * @hw: pointer to the hw struct
0548  * @mib_type: mib type for the query
0549  * @bridgetype: bridge type for the query (remote)
0550  * @dcbcfg: store for LLDPDU data
0551  *
0552  * Query DCB configuration from the Firmware
0553  **/
0554 i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
0555                    u8 bridgetype,
0556                    struct i40e_dcbx_config *dcbcfg)
0557 {
0558     i40e_status ret = 0;
0559     struct i40e_virt_mem mem;
0560     u8 *lldpmib;
0561 
0562     /* Allocate the LLDPDU */
0563     ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
0564     if (ret)
0565         return ret;
0566 
0567     lldpmib = (u8 *)mem.va;
0568     ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
0569                    (void *)lldpmib, I40E_LLDPDU_SIZE,
0570                    NULL, NULL, NULL);
0571     if (ret)
0572         goto free_mem;
0573 
0574     /* Parse LLDP MIB to get dcb configuration */
0575     ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
0576 
0577 free_mem:
0578     i40e_free_virt_mem(hw, &mem);
0579     return ret;
0580 }
0581 
0582 /**
0583  * i40e_cee_to_dcb_v1_config
0584  * @cee_cfg: pointer to CEE v1 response configuration struct
0585  * @dcbcfg: DCB configuration struct
0586  *
0587  * Convert CEE v1 configuration from firmware to DCB configuration
0588  **/
0589 static void i40e_cee_to_dcb_v1_config(
0590             struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
0591             struct i40e_dcbx_config *dcbcfg)
0592 {
0593     u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);
0594     u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
0595     u8 i, tc, err;
0596 
0597     /* CEE PG data to ETS config */
0598     dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
0599 
0600     /* Note that the FW creates the oper_prio_tc nibbles reversed
0601      * from those in the CEE Priority Group sub-TLV.
0602      */
0603     for (i = 0; i < 4; i++) {
0604         tc = (u8)((cee_cfg->oper_prio_tc[i] &
0605              I40E_CEE_PGID_PRIO_0_MASK) >>
0606              I40E_CEE_PGID_PRIO_0_SHIFT);
0607         dcbcfg->etscfg.prioritytable[i * 2] =  tc;
0608         tc = (u8)((cee_cfg->oper_prio_tc[i] &
0609              I40E_CEE_PGID_PRIO_1_MASK) >>
0610              I40E_CEE_PGID_PRIO_1_SHIFT);
0611         dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
0612     }
0613 
0614     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0615         dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
0616 
0617     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
0618         if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
0619             /* Map it to next empty TC */
0620             dcbcfg->etscfg.prioritytable[i] =
0621                         cee_cfg->oper_num_tc - 1;
0622             dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
0623         } else {
0624             dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
0625         }
0626     }
0627 
0628     /* CEE PFC data to ETS config */
0629     dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
0630     dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
0631 
0632     status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
0633           I40E_AQC_CEE_APP_STATUS_SHIFT;
0634     err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
0635     /* Add APPs if Error is False */
0636     if (!err) {
0637         /* CEE operating configuration supports FCoE/iSCSI/FIP only */
0638         dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
0639 
0640         /* FCoE APP */
0641         dcbcfg->app[0].priority =
0642             (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
0643              I40E_AQC_CEE_APP_FCOE_SHIFT;
0644         dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
0645         dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
0646 
0647         /* iSCSI APP */
0648         dcbcfg->app[1].priority =
0649             (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
0650              I40E_AQC_CEE_APP_ISCSI_SHIFT;
0651         dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
0652         dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
0653 
0654         /* FIP APP */
0655         dcbcfg->app[2].priority =
0656             (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
0657              I40E_AQC_CEE_APP_FIP_SHIFT;
0658         dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
0659         dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
0660     }
0661 }
0662 
0663 /**
0664  * i40e_cee_to_dcb_config
0665  * @cee_cfg: pointer to CEE configuration struct
0666  * @dcbcfg: DCB configuration struct
0667  *
0668  * Convert CEE configuration from firmware to DCB configuration
0669  **/
0670 static void i40e_cee_to_dcb_config(
0671                 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
0672                 struct i40e_dcbx_config *dcbcfg)
0673 {
0674     u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
0675     u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
0676     u8 i, tc, err, sync, oper;
0677 
0678     /* CEE PG data to ETS config */
0679     dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
0680 
0681     /* Note that the FW creates the oper_prio_tc nibbles reversed
0682      * from those in the CEE Priority Group sub-TLV.
0683      */
0684     for (i = 0; i < 4; i++) {
0685         tc = (u8)((cee_cfg->oper_prio_tc[i] &
0686              I40E_CEE_PGID_PRIO_0_MASK) >>
0687              I40E_CEE_PGID_PRIO_0_SHIFT);
0688         dcbcfg->etscfg.prioritytable[i * 2] =  tc;
0689         tc = (u8)((cee_cfg->oper_prio_tc[i] &
0690              I40E_CEE_PGID_PRIO_1_MASK) >>
0691              I40E_CEE_PGID_PRIO_1_SHIFT);
0692         dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
0693     }
0694 
0695     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
0696         dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
0697 
0698     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
0699         if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
0700             /* Map it to next empty TC */
0701             dcbcfg->etscfg.prioritytable[i] =
0702                         cee_cfg->oper_num_tc - 1;
0703             dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
0704         } else {
0705             dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
0706         }
0707     }
0708 
0709     /* CEE PFC data to ETS config */
0710     dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
0711     dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
0712 
0713     i = 0;
0714     status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
0715           I40E_AQC_CEE_FCOE_STATUS_SHIFT;
0716     err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
0717     sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
0718     oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
0719     /* Add FCoE APP if Error is False and Oper/Sync is True */
0720     if (!err && sync && oper) {
0721         /* FCoE APP */
0722         dcbcfg->app[i].priority =
0723             (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
0724              I40E_AQC_CEE_APP_FCOE_SHIFT;
0725         dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
0726         dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
0727         i++;
0728     }
0729 
0730     status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
0731           I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
0732     err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
0733     sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
0734     oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
0735     /* Add iSCSI APP if Error is False and Oper/Sync is True */
0736     if (!err && sync && oper) {
0737         /* iSCSI APP */
0738         dcbcfg->app[i].priority =
0739             (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
0740              I40E_AQC_CEE_APP_ISCSI_SHIFT;
0741         dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
0742         dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
0743         i++;
0744     }
0745 
0746     status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
0747           I40E_AQC_CEE_FIP_STATUS_SHIFT;
0748     err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
0749     sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
0750     oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
0751     /* Add FIP APP if Error is False and Oper/Sync is True */
0752     if (!err && sync && oper) {
0753         /* FIP APP */
0754         dcbcfg->app[i].priority =
0755             (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
0756              I40E_AQC_CEE_APP_FIP_SHIFT;
0757         dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
0758         dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
0759         i++;
0760     }
0761     dcbcfg->numapps = i;
0762 }
0763 
0764 /**
0765  * i40e_get_ieee_dcb_config
0766  * @hw: pointer to the hw struct
0767  *
0768  * Get IEEE mode DCB configuration from the Firmware
0769  **/
0770 static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw)
0771 {
0772     i40e_status ret = 0;
0773 
0774     /* IEEE mode */
0775     hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
0776     /* Get Local DCB Config */
0777     ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
0778                      &hw->local_dcbx_config);
0779     if (ret)
0780         goto out;
0781 
0782     /* Get Remote DCB Config */
0783     ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
0784                      I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
0785                      &hw->remote_dcbx_config);
0786     /* Don't treat ENOENT as an error for Remote MIBs */
0787     if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
0788         ret = 0;
0789 
0790 out:
0791     return ret;
0792 }
0793 
0794 /**
0795  * i40e_get_dcb_config
0796  * @hw: pointer to the hw struct
0797  *
0798  * Get DCB configuration from the Firmware
0799  **/
0800 i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
0801 {
0802     i40e_status ret = 0;
0803     struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
0804     struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
0805 
0806     /* If Firmware version < v4.33 on X710/XL710, IEEE only */
0807     if ((hw->mac.type == I40E_MAC_XL710) &&
0808         (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
0809           (hw->aq.fw_maj_ver < 4)))
0810         return i40e_get_ieee_dcb_config(hw);
0811 
0812     /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
0813     if ((hw->mac.type == I40E_MAC_XL710) &&
0814         ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
0815         ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
0816                          sizeof(cee_v1_cfg), NULL);
0817         if (!ret) {
0818             /* CEE mode */
0819             hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
0820             hw->local_dcbx_config.tlv_status =
0821                     le16_to_cpu(cee_v1_cfg.tlv_status);
0822             i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
0823                           &hw->local_dcbx_config);
0824         }
0825     } else {
0826         ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
0827                          sizeof(cee_cfg), NULL);
0828         if (!ret) {
0829             /* CEE mode */
0830             hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
0831             hw->local_dcbx_config.tlv_status =
0832                     le32_to_cpu(cee_cfg.tlv_status);
0833             i40e_cee_to_dcb_config(&cee_cfg,
0834                            &hw->local_dcbx_config);
0835         }
0836     }
0837 
0838     /* CEE mode not enabled try querying IEEE data */
0839     if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
0840         return i40e_get_ieee_dcb_config(hw);
0841 
0842     if (ret)
0843         goto out;
0844 
0845     /* Get CEE DCB Desired Config */
0846     ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
0847                      &hw->desired_dcbx_config);
0848     if (ret)
0849         goto out;
0850 
0851     /* Get Remote DCB Config */
0852     ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
0853                      I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
0854                      &hw->remote_dcbx_config);
0855     /* Don't treat ENOENT as an error for Remote MIBs */
0856     if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
0857         ret = 0;
0858 
0859 out:
0860     return ret;
0861 }
0862 
0863 /**
0864  * i40e_init_dcb
0865  * @hw: pointer to the hw struct
0866  * @enable_mib_change: enable mib change event
0867  *
0868  * Update DCB configuration from the Firmware
0869  **/
0870 i40e_status i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
0871 {
0872     i40e_status ret = 0;
0873     struct i40e_lldp_variables lldp_cfg;
0874     u8 adminstatus = 0;
0875 
0876     if (!hw->func_caps.dcb)
0877         return I40E_NOT_SUPPORTED;
0878 
0879     /* Read LLDP NVM area */
0880     if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
0881         u8 offset = 0;
0882 
0883         if (hw->mac.type == I40E_MAC_XL710)
0884             offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
0885         else if (hw->mac.type == I40E_MAC_X722)
0886             offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
0887         else
0888             return I40E_NOT_SUPPORTED;
0889 
0890         ret = i40e_read_nvm_module_data(hw,
0891                         I40E_SR_EMP_SR_SETTINGS_PTR,
0892                         offset,
0893                         I40E_LLDP_CURRENT_STATUS_OFFSET,
0894                         I40E_LLDP_CURRENT_STATUS_SIZE,
0895                         &lldp_cfg.adminstatus);
0896     } else {
0897         ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
0898     }
0899     if (ret)
0900         return I40E_ERR_NOT_READY;
0901 
0902     /* Get the LLDP AdminStatus for the current port */
0903     adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
0904     adminstatus &= 0xF;
0905 
0906     /* LLDP agent disabled */
0907     if (!adminstatus) {
0908         hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
0909         return I40E_ERR_NOT_READY;
0910     }
0911 
0912     /* Get DCBX status */
0913     ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
0914     if (ret)
0915         return ret;
0916 
0917     /* Check the DCBX Status */
0918     if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
0919         hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
0920         /* Get current DCBX configuration */
0921         ret = i40e_get_dcb_config(hw);
0922         if (ret)
0923             return ret;
0924     } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
0925         return I40E_ERR_NOT_READY;
0926     }
0927 
0928     /* Configure the LLDP MIB change event */
0929     if (enable_mib_change)
0930         ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
0931 
0932     return ret;
0933 }
0934 
0935 /**
0936  * i40e_get_fw_lldp_status
0937  * @hw: pointer to the hw struct
0938  * @lldp_status: pointer to the status enum
0939  *
0940  * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
0941  * Status of agent is reported via @lldp_status parameter.
0942  **/
0943 enum i40e_status_code
0944 i40e_get_fw_lldp_status(struct i40e_hw *hw,
0945             enum i40e_get_fw_lldp_status_resp *lldp_status)
0946 {
0947     struct i40e_virt_mem mem;
0948     i40e_status ret;
0949     u8 *lldpmib;
0950 
0951     if (!lldp_status)
0952         return I40E_ERR_PARAM;
0953 
0954     /* Allocate buffer for the LLDPDU */
0955     ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
0956     if (ret)
0957         return ret;
0958 
0959     lldpmib = (u8 *)mem.va;
0960     ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
0961                    I40E_LLDPDU_SIZE, NULL, NULL, NULL);
0962 
0963     if (!ret) {
0964         *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
0965     } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
0966         /* MIB is not available yet but the agent is running */
0967         *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
0968         ret = 0;
0969     } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
0970         *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
0971         ret = 0;
0972     }
0973 
0974     i40e_free_virt_mem(hw, &mem);
0975     return ret;
0976 }
0977 
0978 /**
0979  * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
0980  * @tlv: Fill the ETS config data in IEEE format
0981  * @dcbcfg: Local store which holds the DCB Config
0982  *
0983  * Prepare IEEE 802.1Qaz ETS CFG TLV
0984  **/
0985 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
0986                   struct i40e_dcbx_config *dcbcfg)
0987 {
0988     u8 priority0, priority1, maxtcwilling = 0;
0989     struct i40e_dcb_ets_config *etscfg;
0990     u16 offset = 0, typelength, i;
0991     u8 *buf = tlv->tlvinfo;
0992     u32 ouisubtype;
0993 
0994     typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
0995             I40E_IEEE_ETS_TLV_LENGTH);
0996     tlv->typelength = htons(typelength);
0997 
0998     ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
0999             I40E_IEEE_SUBTYPE_ETS_CFG);
1000     tlv->ouisubtype = htonl(ouisubtype);
1001 
1002     /* First Octet post subtype
1003      * --------------------------
1004      * |will-|CBS  | Re-  | Max |
1005      * |ing  |     |served| TCs |
1006      * --------------------------
1007      * |1bit | 1bit|3 bits|3bits|
1008      */
1009     etscfg = &dcbcfg->etscfg;
1010     if (etscfg->willing)
1011         maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
1012     maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
1013     buf[offset] = maxtcwilling;
1014 
1015     /* Move offset to Priority Assignment Table */
1016     offset++;
1017 
1018     /* Priority Assignment Table (4 octets)
1019      * Octets:|    1    |    2    |    3    |    4    |
1020      *        -----------------------------------------
1021      *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1022      *        -----------------------------------------
1023      *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
1024      *        -----------------------------------------
1025      */
1026     for (i = 0; i < 4; i++) {
1027         priority0 = etscfg->prioritytable[i * 2] & 0xF;
1028         priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
1029         buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1030                 priority1;
1031         offset++;
1032     }
1033 
1034     /* TC Bandwidth Table (8 octets)
1035      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1036      *        ---------------------------------
1037      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1038      *        ---------------------------------
1039      */
1040     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1041         buf[offset++] = etscfg->tcbwtable[i];
1042 
1043     /* TSA Assignment Table (8 octets)
1044      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1045      *        ---------------------------------
1046      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1047      *        ---------------------------------
1048      */
1049     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1050         buf[offset++] = etscfg->tsatable[i];
1051 }
1052 
1053 /**
1054  * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1055  * @tlv: Fill ETS Recommended TLV in IEEE format
1056  * @dcbcfg: Local store which holds the DCB Config
1057  *
1058  * Prepare IEEE 802.1Qaz ETS REC TLV
1059  **/
1060 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
1061                      struct i40e_dcbx_config *dcbcfg)
1062 {
1063     struct i40e_dcb_ets_config *etsrec;
1064     u16 offset = 0, typelength, i;
1065     u8 priority0, priority1;
1066     u8 *buf = tlv->tlvinfo;
1067     u32 ouisubtype;
1068 
1069     typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1070             I40E_IEEE_ETS_TLV_LENGTH);
1071     tlv->typelength = htons(typelength);
1072 
1073     ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1074             I40E_IEEE_SUBTYPE_ETS_REC);
1075     tlv->ouisubtype = htonl(ouisubtype);
1076 
1077     etsrec = &dcbcfg->etsrec;
1078     /* First Octet is reserved */
1079     /* Move offset to Priority Assignment Table */
1080     offset++;
1081 
1082     /* Priority Assignment Table (4 octets)
1083      * Octets:|    1    |    2    |    3    |    4    |
1084      *        -----------------------------------------
1085      *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1086      *        -----------------------------------------
1087      *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
1088      *        -----------------------------------------
1089      */
1090     for (i = 0; i < 4; i++) {
1091         priority0 = etsrec->prioritytable[i * 2] & 0xF;
1092         priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
1093         buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1094                 priority1;
1095         offset++;
1096     }
1097 
1098     /* TC Bandwidth Table (8 octets)
1099      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1100      *        ---------------------------------
1101      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1102      *        ---------------------------------
1103      */
1104     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1105         buf[offset++] = etsrec->tcbwtable[i];
1106 
1107     /* TSA Assignment Table (8 octets)
1108      * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1109      *        ---------------------------------
1110      *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1111      *        ---------------------------------
1112      */
1113     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1114         buf[offset++] = etsrec->tsatable[i];
1115 }
1116 
1117 /**
1118  * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1119  * @tlv: Fill PFC TLV in IEEE format
1120  * @dcbcfg: Local store to get PFC CFG data
1121  *
1122  * Prepare IEEE 802.1Qaz PFC CFG TLV
1123  **/
1124 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
1125                   struct i40e_dcbx_config *dcbcfg)
1126 {
1127     u8 *buf = tlv->tlvinfo;
1128     u32 ouisubtype;
1129     u16 typelength;
1130 
1131     typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1132             I40E_IEEE_PFC_TLV_LENGTH);
1133     tlv->typelength = htons(typelength);
1134 
1135     ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1136             I40E_IEEE_SUBTYPE_PFC_CFG);
1137     tlv->ouisubtype = htonl(ouisubtype);
1138 
1139     /* ----------------------------------------
1140      * |will-|MBC  | Re-  | PFC |  PFC Enable  |
1141      * |ing  |     |served| cap |              |
1142      * -----------------------------------------
1143      * |1bit | 1bit|2 bits|4bits| 1 octet      |
1144      */
1145     if (dcbcfg->pfc.willing)
1146         buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
1147 
1148     if (dcbcfg->pfc.mbc)
1149         buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
1150 
1151     buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1152     buf[1] = dcbcfg->pfc.pfcenable;
1153 }
1154 
1155 /**
1156  * i40e_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format
1157  * @tlv: Fill APP TLV in IEEE format
1158  * @dcbcfg: Local store to get APP CFG data
1159  *
1160  * Prepare IEEE 802.1Qaz APP CFG TLV
1161  **/
1162 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
1163                       struct i40e_dcbx_config *dcbcfg)
1164 {
1165     u16 typelength, length, offset = 0;
1166     u8 priority, selector, i = 0;
1167     u8 *buf = tlv->tlvinfo;
1168     u32 ouisubtype;
1169 
1170     /* No APP TLVs then just return */
1171     if (dcbcfg->numapps == 0)
1172         return;
1173     ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1174             I40E_IEEE_SUBTYPE_APP_PRI);
1175     tlv->ouisubtype = htonl(ouisubtype);
1176 
1177     /* Move offset to App Priority Table */
1178     offset++;
1179     /* Application Priority Table (3 octets)
1180      * Octets:|         1          |    2    |    3    |
1181      *        -----------------------------------------
1182      *        |Priority|Rsrvd| Sel |    Protocol ID    |
1183      *        -----------------------------------------
1184      *   Bits:|23    21|20 19|18 16|15                0|
1185      *        -----------------------------------------
1186      */
1187     while (i < dcbcfg->numapps) {
1188         priority = dcbcfg->app[i].priority & 0x7;
1189         selector = dcbcfg->app[i].selector & 0x7;
1190         buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
1191         buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
1192         buf[offset + 2] =  dcbcfg->app[i].protocolid & 0xFF;
1193         /* Move to next app */
1194         offset += 3;
1195         i++;
1196         if (i >= I40E_DCBX_MAX_APPS)
1197             break;
1198     }
1199     /* length includes size of ouisubtype + 1 reserved + 3*numapps */
1200     length = sizeof(tlv->ouisubtype) + 1 + (i * 3);
1201     typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1202         (length & 0x1FF));
1203     tlv->typelength = htons(typelength);
1204 }
1205 
1206 /**
1207  * i40e_add_dcb_tlv - Add all IEEE TLVs
1208  * @tlv: pointer to org tlv
1209  * @dcbcfg: pointer to modified dcbx config structure *
1210  * @tlvid: tlv id to be added
1211  * add tlv information
1212  **/
1213 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
1214                  struct i40e_dcbx_config *dcbcfg,
1215                  u16 tlvid)
1216 {
1217     switch (tlvid) {
1218     case I40E_IEEE_TLV_ID_ETS_CFG:
1219         i40e_add_ieee_ets_tlv(tlv, dcbcfg);
1220         break;
1221     case I40E_IEEE_TLV_ID_ETS_REC:
1222         i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
1223         break;
1224     case I40E_IEEE_TLV_ID_PFC_CFG:
1225         i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
1226         break;
1227     case I40E_IEEE_TLV_ID_APP_PRI:
1228         i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
1229         break;
1230     default:
1231         break;
1232     }
1233 }
1234 
1235 /**
1236  * i40e_set_dcb_config - Set the local LLDP MIB to FW
1237  * @hw: pointer to the hw struct
1238  *
1239  * Set DCB configuration to the Firmware
1240  **/
1241 i40e_status i40e_set_dcb_config(struct i40e_hw *hw)
1242 {
1243     struct i40e_dcbx_config *dcbcfg;
1244     struct i40e_virt_mem mem;
1245     u8 mib_type, *lldpmib;
1246     i40e_status ret;
1247     u16 miblen;
1248 
1249     /* update the hw local config */
1250     dcbcfg = &hw->local_dcbx_config;
1251     /* Allocate the LLDPDU */
1252     ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
1253     if (ret)
1254         return ret;
1255 
1256     mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
1257     if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
1258         mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
1259                 SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
1260     }
1261     lldpmib = (u8 *)mem.va;
1262     i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
1263     ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
1264 
1265     i40e_free_virt_mem(hw, &mem);
1266     return ret;
1267 }
1268 
1269 /**
1270  * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1271  * @lldpmib: pointer to mib to be output
1272  * @miblen: pointer to u16 for length of lldpmib
1273  * @dcbcfg: store for LLDPDU data
1274  *
1275  * send DCB configuration to FW
1276  **/
1277 i40e_status i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
1278                     struct i40e_dcbx_config *dcbcfg)
1279 {
1280     u16 length, offset = 0, tlvid, typelength;
1281     struct i40e_lldp_org_tlv *tlv;
1282 
1283     tlv = (struct i40e_lldp_org_tlv *)lldpmib;
1284     tlvid = I40E_TLV_ID_START;
1285     do {
1286         i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1287         typelength = ntohs(tlv->typelength);
1288         length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
1289                 I40E_LLDP_TLV_LEN_SHIFT);
1290         if (length)
1291             offset += length + I40E_IEEE_TLV_HEADER_LENGTH;
1292         /* END TLV or beyond LLDPDU size */
1293         if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU ||
1294             offset >= I40E_LLDPDU_SIZE)
1295             break;
1296         /* Move to next TLV */
1297         if (length)
1298             tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
1299                   sizeof(tlv->typelength) + length);
1300     } while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU);
1301     *miblen = offset;
1302     return I40E_SUCCESS;
1303 }
1304 
1305 /**
1306  * i40e_dcb_hw_rx_fifo_config
1307  * @hw: pointer to the hw struct
1308  * @ets_mode: Strict Priority or Round Robin mode
1309  * @non_ets_mode: Strict Priority or Round Robin
1310  * @max_exponent: Exponent to calculate max refill credits
1311  * @lltc_map: Low latency TC bitmap
1312  *
1313  * Configure HW Rx FIFO as part of DCB configuration.
1314  **/
1315 void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,
1316                 enum i40e_dcb_arbiter_mode ets_mode,
1317                 enum i40e_dcb_arbiter_mode non_ets_mode,
1318                 u32 max_exponent,
1319                 u8 lltc_map)
1320 {
1321     u32 reg = rd32(hw, I40E_PRTDCB_RETSC);
1322 
1323     reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;
1324     reg |= ((u32)ets_mode << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) &
1325         I40E_PRTDCB_RETSC_ETS_MODE_MASK;
1326 
1327     reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
1328     reg |= ((u32)non_ets_mode << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) &
1329         I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
1330 
1331     reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
1332     reg |= (max_exponent << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) &
1333         I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
1334 
1335     reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;
1336     reg |= (lltc_map << I40E_PRTDCB_RETSC_LLTC_SHIFT) &
1337         I40E_PRTDCB_RETSC_LLTC_MASK;
1338     wr32(hw, I40E_PRTDCB_RETSC, reg);
1339 }
1340 
1341 /**
1342  * i40e_dcb_hw_rx_cmd_monitor_config
1343  * @hw: pointer to the hw struct
1344  * @num_tc: Total number of traffic class
1345  * @num_ports: Total number of ports on device
1346  *
1347  * Configure HW Rx command monitor as part of DCB configuration.
1348  **/
1349 void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
1350                        u8 num_tc, u8 num_ports)
1351 {
1352     u32 threshold;
1353     u32 fifo_size;
1354     u32 reg;
1355 
1356     /* Set the threshold and fifo_size based on number of ports */
1357     switch (num_ports) {
1358     case 1:
1359         threshold = I40E_DCB_1_PORT_THRESHOLD;
1360         fifo_size = I40E_DCB_1_PORT_FIFO_SIZE;
1361         break;
1362     case 2:
1363         if (num_tc > 4) {
1364             threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC;
1365             fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC;
1366         } else {
1367             threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC;
1368             fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC;
1369         }
1370         break;
1371     case 4:
1372         if (num_tc > 4) {
1373             threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC;
1374             fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC;
1375         } else {
1376             threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC;
1377             fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC;
1378         }
1379         break;
1380     default:
1381         i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n",
1382                (u32)num_ports);
1383         return;
1384     }
1385 
1386     /* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR
1387      * based on the number of ports and traffic classes for a given port as
1388      * part of DCB configuration.
1389      */
1390     reg = rd32(hw, I40E_PRT_SWR_PM_THR);
1391     reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
1392     reg |= (threshold << I40E_PRT_SWR_PM_THR_THRESHOLD_SHIFT) &
1393         I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
1394     wr32(hw, I40E_PRT_SWR_PM_THR, reg);
1395 
1396     reg = rd32(hw, I40E_PRTDCB_RPPMC);
1397     reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
1398     reg |= (fifo_size << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) &
1399         I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
1400     wr32(hw, I40E_PRTDCB_RPPMC, reg);
1401 }
1402 
1403 /**
1404  * i40e_dcb_hw_pfc_config
1405  * @hw: pointer to the hw struct
1406  * @pfc_en: Bitmap of PFC enabled priorities
1407  * @prio_tc: priority to tc assignment indexed by priority
1408  *
1409  * Configure HW Priority Flow Controller as part of DCB configuration.
1410  **/
1411 void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
1412                 u8 pfc_en, u8 *prio_tc)
1413 {
1414     u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2;
1415     u32 link_speed = hw->phy.link_info.link_speed;
1416     u8 first_pfc_prio = 0;
1417     u8 num_pfc_tc = 0;
1418     u8 tc2pfc = 0;
1419     u32 reg;
1420     u8 i;
1421 
1422     /* Get Number of PFC TCs and TC2PFC map */
1423     for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
1424         if (pfc_en & BIT(i)) {
1425             if (!first_pfc_prio)
1426                 first_pfc_prio = i;
1427             /* Set bit for the PFC TC */
1428             tc2pfc |= BIT(prio_tc[i]);
1429             num_pfc_tc++;
1430         }
1431     }
1432 
1433     switch (link_speed) {
1434     case I40E_LINK_SPEED_10GB:
1435         reg = rd32(hw, I40E_PRTDCB_MFLCN);
1436         reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) &
1437             I40E_PRTDCB_MFLCN_DPF_MASK;
1438         reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;
1439         reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;
1440         if (pfc_en) {
1441             reg |= BIT(I40E_PRTDCB_MFLCN_RPFCM_SHIFT) &
1442                 I40E_PRTDCB_MFLCN_RPFCM_MASK;
1443             reg |= ((u32)pfc_en << I40E_PRTDCB_MFLCN_RPFCE_SHIFT) &
1444                 I40E_PRTDCB_MFLCN_RPFCE_MASK;
1445         }
1446         wr32(hw, I40E_PRTDCB_MFLCN, reg);
1447 
1448         reg = rd32(hw, I40E_PRTDCB_FCCFG);
1449         reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
1450         if (pfc_en)
1451             reg |= (I40E_DCB_PFC_ENABLED <<
1452                 I40E_PRTDCB_FCCFG_TFCE_SHIFT) &
1453                 I40E_PRTDCB_FCCFG_TFCE_MASK;
1454         wr32(hw, I40E_PRTDCB_FCCFG, reg);
1455 
1456         /* FCTTV and FCRTV to be set by default */
1457         break;
1458     case I40E_LINK_SPEED_40GB:
1459         reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
1460         reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
1461         wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);
1462 
1463         reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
1464         reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
1465         reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &
1466             I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK;
1467         wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);
1468 
1469         reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
1470         reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
1471         reg |= ((u32)pfc_en <<
1472                I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) &
1473             I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
1474         wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);
1475 
1476         reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
1477         reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
1478         reg |= ((u32)pfc_en <<
1479                I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) &
1480             I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
1481         wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);
1482 
1483         for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {
1484             reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));
1485             reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
1486             if (pfc_en) {
1487                 reg |= ((u32)refresh_time <<
1488                     I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) &
1489                     I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
1490             }
1491             wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);
1492         }
1493         /* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF
1494          * for all user priorities
1495          */
1496         break;
1497     }
1498 
1499     reg = rd32(hw, I40E_PRTDCB_TC2PFC);
1500     reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
1501     reg |= ((u32)tc2pfc << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) &
1502         I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
1503     wr32(hw, I40E_PRTDCB_TC2PFC, reg);
1504 
1505     reg = rd32(hw, I40E_PRTDCB_RUP);
1506     reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;
1507     reg |= ((u32)first_pfc_prio << I40E_PRTDCB_RUP_NOVLANUP_SHIFT) &
1508          I40E_PRTDCB_RUP_NOVLANUP_MASK;
1509     wr32(hw, I40E_PRTDCB_RUP, reg);
1510 
1511     reg = rd32(hw, I40E_PRTDCB_TDPMC);
1512     reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
1513     if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
1514         reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &
1515             I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
1516     }
1517     wr32(hw, I40E_PRTDCB_TDPMC, reg);
1518 
1519     reg = rd32(hw, I40E_PRTDCB_TCPMC);
1520     reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
1521     if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
1522         reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &
1523             I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
1524     }
1525     wr32(hw, I40E_PRTDCB_TCPMC, reg);
1526 }
1527 
1528 /**
1529  * i40e_dcb_hw_set_num_tc
1530  * @hw: pointer to the hw struct
1531  * @num_tc: number of traffic classes
1532  *
1533  * Configure number of traffic classes in HW
1534  **/
1535 void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
1536 {
1537     u32 reg = rd32(hw, I40E_PRTDCB_GENC);
1538 
1539     reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;
1540     reg |= ((u32)num_tc << I40E_PRTDCB_GENC_NUMTC_SHIFT) &
1541         I40E_PRTDCB_GENC_NUMTC_MASK;
1542     wr32(hw, I40E_PRTDCB_GENC, reg);
1543 }
1544 
1545 /**
1546  * i40e_dcb_hw_get_num_tc
1547  * @hw: pointer to the hw struct
1548  *
1549  * Returns number of traffic classes configured in HW
1550  **/
1551 u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
1552 {
1553     u32 reg = rd32(hw, I40E_PRTDCB_GENC);
1554 
1555     return (u8)((reg & I40E_PRTDCB_GENC_NUMTC_MASK) >>
1556         I40E_PRTDCB_GENC_NUMTC_SHIFT);
1557 }
1558 
1559 /**
1560  * i40e_dcb_hw_rx_ets_bw_config
1561  * @hw: pointer to the hw struct
1562  * @bw_share: Bandwidth share indexed per traffic class
1563  * @mode: Strict Priority or Round Robin mode between UP sharing same
1564  * traffic class
1565  * @prio_type: TC is ETS enabled or strict priority
1566  *
1567  * Configure HW Rx ETS bandwidth as part of DCB configuration.
1568  **/
1569 void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
1570                   u8 *mode, u8 *prio_type)
1571 {
1572     u32 reg;
1573     u8 i;
1574 
1575     for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {
1576         reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
1577         reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK     |
1578              I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
1579              I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);
1580         reg |= ((u32)bw_share[i] << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) &
1581              I40E_PRTDCB_RETSTCC_BWSHARE_MASK;
1582         reg |= ((u32)mode[i] << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) &
1583              I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK;
1584         reg |= ((u32)prio_type[i] << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) &
1585              I40E_PRTDCB_RETSTCC_ETSTC_MASK;
1586         wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);
1587     }
1588 }
1589 
1590 /**
1591  * i40e_dcb_hw_rx_up2tc_config
1592  * @hw: pointer to the hw struct
1593  * @prio_tc: priority to tc assignment indexed by priority
1594  *
1595  * Configure HW Rx UP2TC map as part of DCB configuration.
1596  **/
1597 void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)
1598 {
1599     u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC);
1600 #define I40E_UP2TC_REG(val, i) \
1601         (((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \
1602           I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)
1603 
1604     reg |= I40E_UP2TC_REG(prio_tc[0], 0);
1605     reg |= I40E_UP2TC_REG(prio_tc[1], 1);
1606     reg |= I40E_UP2TC_REG(prio_tc[2], 2);
1607     reg |= I40E_UP2TC_REG(prio_tc[3], 3);
1608     reg |= I40E_UP2TC_REG(prio_tc[4], 4);
1609     reg |= I40E_UP2TC_REG(prio_tc[5], 5);
1610     reg |= I40E_UP2TC_REG(prio_tc[6], 6);
1611     reg |= I40E_UP2TC_REG(prio_tc[7], 7);
1612 
1613     wr32(hw, I40E_PRTDCB_RUP2TC, reg);
1614 }
1615 
1616 /**
1617  * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes
1618  * @hw: pointer to the hw struct
1619  * @num_ports: Number of available ports on the device
1620  * @eee_enabled: EEE enabled for the given port
1621  * @pfc_en: Bit map of PFC enabled traffic classes
1622  * @mfs_tc: Array of max frame size for each traffic class
1623  * @pb_cfg: pointer to packet buffer configuration
1624  *
1625  * Calculate the shared and dedicated per TC pool sizes,
1626  * watermarks and threshold values.
1627  **/
1628 void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,
1629                       u8 num_ports, bool eee_enabled,
1630                       u8 pfc_en, u32 *mfs_tc,
1631                       struct i40e_rx_pb_config *pb_cfg)
1632 {
1633     u32 pool_size[I40E_MAX_TRAFFIC_CLASS];
1634     u32 high_wm[I40E_MAX_TRAFFIC_CLASS];
1635     u32 low_wm[I40E_MAX_TRAFFIC_CLASS];
1636     u32 total_pool_size = 0;
1637     int shared_pool_size; /* Need signed variable */
1638     u32 port_pb_size;
1639     u32 mfs_max = 0;
1640     u32 pcirtt;
1641     u8 i;
1642 
1643     /* Get the MFS(max) for the port */
1644     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1645         if (mfs_tc[i] > mfs_max)
1646             mfs_max = mfs_tc[i];
1647     }
1648 
1649     pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);
1650 
1651     /* Calculate effective Rx PB size per port */
1652     port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports;
1653     if (eee_enabled)
1654         port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);
1655     port_pb_size -= mfs_max;
1656 
1657     /* Step 1 Calculating tc pool/shared pool sizes and watermarks */
1658     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1659         if (pfc_en & BIT(i)) {
1660             low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR *
1661                      mfs_tc[i]) + pcirtt;
1662             high_wm[i] = low_wm[i];
1663             high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)
1664                     ? mfs_max : I40E_MAX_FRAME_SIZE);
1665             pool_size[i] = high_wm[i];
1666             pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,
1667                                 mfs_tc[i]));
1668         } else {
1669             low_wm[i] = 0;
1670             pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR *
1671                     mfs_tc[i]) + pcirtt;
1672             high_wm[i] = pool_size[i];
1673         }
1674         total_pool_size += pool_size[i];
1675     }
1676 
1677     shared_pool_size = port_pb_size - total_pool_size;
1678     if (shared_pool_size > 0) {
1679         pb_cfg->shared_pool_size = shared_pool_size;
1680         pb_cfg->shared_pool_high_wm = shared_pool_size;
1681         pb_cfg->shared_pool_low_wm = 0;
1682         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1683             pb_cfg->shared_pool_low_thresh[i] = 0;
1684             pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;
1685             pb_cfg->tc_pool_size[i] = pool_size[i];
1686             pb_cfg->tc_pool_high_wm[i] = high_wm[i];
1687             pb_cfg->tc_pool_low_wm[i] = low_wm[i];
1688         }
1689 
1690     } else {
1691         i40e_debug(hw, I40E_DEBUG_DCB,
1692                "The shared pool size for the port is negative %d.\n",
1693                shared_pool_size);
1694     }
1695 }
1696 
1697 /**
1698  * i40e_dcb_hw_rx_pb_config
1699  * @hw: pointer to the hw struct
1700  * @old_pb_cfg: Existing Rx Packet buffer configuration
1701  * @new_pb_cfg: New Rx Packet buffer configuration
1702  *
1703  * Program the Rx Packet Buffer registers.
1704  **/
1705 void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,
1706                   struct i40e_rx_pb_config *old_pb_cfg,
1707                   struct i40e_rx_pb_config *new_pb_cfg)
1708 {
1709     u32 old_val;
1710     u32 new_val;
1711     u32 reg;
1712     u8 i;
1713 
1714     /* The Rx Packet buffer register programming needs to be done in a
1715      * certain order and the following code is based on that
1716      * requirement.
1717      */
1718 
1719     /* Program the shared pool low water mark per port if decreasing */
1720     old_val = old_pb_cfg->shared_pool_low_wm;
1721     new_val = new_pb_cfg->shared_pool_low_wm;
1722     if (new_val < old_val) {
1723         reg = rd32(hw, I40E_PRTRPB_SLW);
1724         reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
1725         reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
1726             I40E_PRTRPB_SLW_SLW_MASK;
1727         wr32(hw, I40E_PRTRPB_SLW, reg);
1728     }
1729 
1730     /* Program the shared pool low threshold and tc pool
1731      * low water mark per TC that are decreasing.
1732      */
1733     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1734         old_val = old_pb_cfg->shared_pool_low_thresh[i];
1735         new_val = new_pb_cfg->shared_pool_low_thresh[i];
1736         if (new_val < old_val) {
1737             reg = rd32(hw, I40E_PRTRPB_SLT(i));
1738             reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
1739             reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
1740                 I40E_PRTRPB_SLT_SLT_TCN_MASK;
1741             wr32(hw, I40E_PRTRPB_SLT(i), reg);
1742         }
1743 
1744         old_val = old_pb_cfg->tc_pool_low_wm[i];
1745         new_val = new_pb_cfg->tc_pool_low_wm[i];
1746         if (new_val < old_val) {
1747             reg = rd32(hw, I40E_PRTRPB_DLW(i));
1748             reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
1749             reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
1750                 I40E_PRTRPB_DLW_DLW_TCN_MASK;
1751             wr32(hw, I40E_PRTRPB_DLW(i), reg);
1752         }
1753     }
1754 
1755     /* Program the shared pool high water mark per port if decreasing */
1756     old_val = old_pb_cfg->shared_pool_high_wm;
1757     new_val = new_pb_cfg->shared_pool_high_wm;
1758     if (new_val < old_val) {
1759         reg = rd32(hw, I40E_PRTRPB_SHW);
1760         reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
1761         reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
1762             I40E_PRTRPB_SHW_SHW_MASK;
1763         wr32(hw, I40E_PRTRPB_SHW, reg);
1764     }
1765 
1766     /* Program the shared pool high threshold and tc pool
1767      * high water mark per TC that are decreasing.
1768      */
1769     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1770         old_val = old_pb_cfg->shared_pool_high_thresh[i];
1771         new_val = new_pb_cfg->shared_pool_high_thresh[i];
1772         if (new_val < old_val) {
1773             reg = rd32(hw, I40E_PRTRPB_SHT(i));
1774             reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
1775             reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
1776                 I40E_PRTRPB_SHT_SHT_TCN_MASK;
1777             wr32(hw, I40E_PRTRPB_SHT(i), reg);
1778         }
1779 
1780         old_val = old_pb_cfg->tc_pool_high_wm[i];
1781         new_val = new_pb_cfg->tc_pool_high_wm[i];
1782         if (new_val < old_val) {
1783             reg = rd32(hw, I40E_PRTRPB_DHW(i));
1784             reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
1785             reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
1786                 I40E_PRTRPB_DHW_DHW_TCN_MASK;
1787             wr32(hw, I40E_PRTRPB_DHW(i), reg);
1788         }
1789     }
1790 
1791     /* Write Dedicated Pool Sizes per TC */
1792     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1793         new_val = new_pb_cfg->tc_pool_size[i];
1794         reg = rd32(hw, I40E_PRTRPB_DPS(i));
1795         reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;
1796         reg |= (new_val << I40E_PRTRPB_DPS_DPS_TCN_SHIFT) &
1797             I40E_PRTRPB_DPS_DPS_TCN_MASK;
1798         wr32(hw, I40E_PRTRPB_DPS(i), reg);
1799     }
1800 
1801     /* Write Shared Pool Size per port */
1802     new_val = new_pb_cfg->shared_pool_size;
1803     reg = rd32(hw, I40E_PRTRPB_SPS);
1804     reg &= ~I40E_PRTRPB_SPS_SPS_MASK;
1805     reg |= (new_val << I40E_PRTRPB_SPS_SPS_SHIFT) &
1806         I40E_PRTRPB_SPS_SPS_MASK;
1807     wr32(hw, I40E_PRTRPB_SPS, reg);
1808 
1809     /* Program the shared pool low water mark per port if increasing */
1810     old_val = old_pb_cfg->shared_pool_low_wm;
1811     new_val = new_pb_cfg->shared_pool_low_wm;
1812     if (new_val > old_val) {
1813         reg = rd32(hw, I40E_PRTRPB_SLW);
1814         reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
1815         reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
1816             I40E_PRTRPB_SLW_SLW_MASK;
1817         wr32(hw, I40E_PRTRPB_SLW, reg);
1818     }
1819 
1820     /* Program the shared pool low threshold and tc pool
1821      * low water mark per TC that are increasing.
1822      */
1823     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1824         old_val = old_pb_cfg->shared_pool_low_thresh[i];
1825         new_val = new_pb_cfg->shared_pool_low_thresh[i];
1826         if (new_val > old_val) {
1827             reg = rd32(hw, I40E_PRTRPB_SLT(i));
1828             reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
1829             reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
1830                 I40E_PRTRPB_SLT_SLT_TCN_MASK;
1831             wr32(hw, I40E_PRTRPB_SLT(i), reg);
1832         }
1833 
1834         old_val = old_pb_cfg->tc_pool_low_wm[i];
1835         new_val = new_pb_cfg->tc_pool_low_wm[i];
1836         if (new_val > old_val) {
1837             reg = rd32(hw, I40E_PRTRPB_DLW(i));
1838             reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
1839             reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
1840                 I40E_PRTRPB_DLW_DLW_TCN_MASK;
1841             wr32(hw, I40E_PRTRPB_DLW(i), reg);
1842         }
1843     }
1844 
1845     /* Program the shared pool high water mark per port if increasing */
1846     old_val = old_pb_cfg->shared_pool_high_wm;
1847     new_val = new_pb_cfg->shared_pool_high_wm;
1848     if (new_val > old_val) {
1849         reg = rd32(hw, I40E_PRTRPB_SHW);
1850         reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
1851         reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
1852             I40E_PRTRPB_SHW_SHW_MASK;
1853         wr32(hw, I40E_PRTRPB_SHW, reg);
1854     }
1855 
1856     /* Program the shared pool high threshold and tc pool
1857      * high water mark per TC that are increasing.
1858      */
1859     for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1860         old_val = old_pb_cfg->shared_pool_high_thresh[i];
1861         new_val = new_pb_cfg->shared_pool_high_thresh[i];
1862         if (new_val > old_val) {
1863             reg = rd32(hw, I40E_PRTRPB_SHT(i));
1864             reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
1865             reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
1866                 I40E_PRTRPB_SHT_SHT_TCN_MASK;
1867             wr32(hw, I40E_PRTRPB_SHT(i), reg);
1868         }
1869 
1870         old_val = old_pb_cfg->tc_pool_high_wm[i];
1871         new_val = new_pb_cfg->tc_pool_high_wm[i];
1872         if (new_val > old_val) {
1873             reg = rd32(hw, I40E_PRTRPB_DHW(i));
1874             reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
1875             reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
1876                 I40E_PRTRPB_DHW_DHW_TCN_MASK;
1877             wr32(hw, I40E_PRTRPB_DHW(i), reg);
1878         }
1879     }
1880 }
1881 
1882 /**
1883  * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
1884  * @hw: pointer to the HW structure
1885  * @lldp_cfg: pointer to hold lldp configuration variables
1886  * @module: address of the module pointer
1887  * @word_offset: offset of LLDP configuration
1888  *
1889  * Reads the LLDP configuration data from NVM using passed addresses
1890  **/
1891 static i40e_status _i40e_read_lldp_cfg(struct i40e_hw *hw,
1892                        struct i40e_lldp_variables *lldp_cfg,
1893                        u8 module, u32 word_offset)
1894 {
1895     u32 address, offset = (2 * word_offset);
1896     i40e_status ret;
1897     __le16 raw_mem;
1898     u16 mem;
1899 
1900     ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1901     if (ret)
1902         return ret;
1903 
1904     ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
1905                    true, NULL);
1906     i40e_release_nvm(hw);
1907     if (ret)
1908         return ret;
1909 
1910     mem = le16_to_cpu(raw_mem);
1911     /* Check if this pointer needs to be read in word size or 4K sector
1912      * units.
1913      */
1914     if (mem & I40E_PTR_TYPE)
1915         address = (0x7FFF & mem) * 4096;
1916     else
1917         address = (0x7FFF & mem) * 2;
1918 
1919     ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1920     if (ret)
1921         goto err_lldp_cfg;
1922 
1923     ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
1924                    true, NULL);
1925     i40e_release_nvm(hw);
1926     if (ret)
1927         return ret;
1928 
1929     mem = le16_to_cpu(raw_mem);
1930     offset = mem + word_offset;
1931     offset *= 2;
1932 
1933     ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1934     if (ret)
1935         goto err_lldp_cfg;
1936 
1937     ret = i40e_aq_read_nvm(hw, 0, address + offset,
1938                    sizeof(struct i40e_lldp_variables), lldp_cfg,
1939                    true, NULL);
1940     i40e_release_nvm(hw);
1941 
1942 err_lldp_cfg:
1943     return ret;
1944 }
1945 
1946 /**
1947  * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1948  * @hw: pointer to the HW structure
1949  * @lldp_cfg: pointer to hold lldp configuration variables
1950  *
1951  * Reads the LLDP configuration data from NVM
1952  **/
1953 i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
1954                    struct i40e_lldp_variables *lldp_cfg)
1955 {
1956     i40e_status ret = 0;
1957     u32 mem;
1958 
1959     if (!lldp_cfg)
1960         return I40E_ERR_PARAM;
1961 
1962     ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1963     if (ret)
1964         return ret;
1965 
1966     ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
1967                    &mem, true, NULL);
1968     i40e_release_nvm(hw);
1969     if (ret)
1970         return ret;
1971 
1972     /* Read a bit that holds information whether we are running flat or
1973      * structured NVM image. Flat image has LLDP configuration in shadow
1974      * ram, so there is a need to pass different addresses for both cases.
1975      */
1976     if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
1977         /* Flat NVM case */
1978         ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
1979                       I40E_SR_LLDP_CFG_PTR);
1980     } else {
1981         /* Good old structured NVM image */
1982         ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
1983                       I40E_NVM_LLDP_CFG_PTR);
1984     }
1985 
1986     return ret;
1987 }