linux/drivers/net/ethernet/intel/i40e/i40e_dcb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2013 - 2021 Intel Corporation. */
   3
   4#include "i40e_adminq.h"
   5#include "i40e_prototype.h"
   6#include "i40e_dcb.h"
   7
   8/**
   9 * i40e_get_dcbx_status
  10 * @hw: pointer to the hw struct
  11 * @status: Embedded DCBX Engine Status
  12 *
  13 * Get the DCBX status from the Firmware
  14 **/
  15i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
  16{
  17        u32 reg;
  18
  19        if (!status)
  20                return I40E_ERR_PARAM;
  21
  22        reg = rd32(hw, I40E_PRTDCB_GENS);
  23        *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
  24                        I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
  25
  26        return 0;
  27}
  28
  29/**
  30 * i40e_parse_ieee_etscfg_tlv
  31 * @tlv: IEEE 802.1Qaz ETS CFG TLV
  32 * @dcbcfg: Local store to update ETS CFG data
  33 *
  34 * Parses IEEE 802.1Qaz ETS CFG TLV
  35 **/
  36static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
  37                                       struct i40e_dcbx_config *dcbcfg)
  38{
  39        struct i40e_dcb_ets_config *etscfg;
  40        u8 *buf = tlv->tlvinfo;
  41        u16 offset = 0;
  42        u8 priority;
  43        int i;
  44
  45        /* First Octet post subtype
  46         * --------------------------
  47         * |will-|CBS  | Re-  | Max |
  48         * |ing  |     |served| TCs |
  49         * --------------------------
  50         * |1bit | 1bit|3 bits|3bits|
  51         */
  52        etscfg = &dcbcfg->etscfg;
  53        etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
  54                               I40E_IEEE_ETS_WILLING_SHIFT);
  55        etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
  56                           I40E_IEEE_ETS_CBS_SHIFT);
  57        etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
  58                              I40E_IEEE_ETS_MAXTC_SHIFT);
  59
  60        /* Move offset to Priority Assignment Table */
  61        offset++;
  62
  63        /* Priority Assignment Table (4 octets)
  64         * Octets:|    1    |    2    |    3    |    4    |
  65         *        -----------------------------------------
  66         *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  67         *        -----------------------------------------
  68         *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
  69         *        -----------------------------------------
  70         */
  71        for (i = 0; i < 4; i++) {
  72                priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
  73                                I40E_IEEE_ETS_PRIO_1_SHIFT);
  74                etscfg->prioritytable[i * 2] =  priority;
  75                priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
  76                                I40E_IEEE_ETS_PRIO_0_SHIFT);
  77                etscfg->prioritytable[i * 2 + 1] = priority;
  78                offset++;
  79        }
  80
  81        /* TC Bandwidth Table (8 octets)
  82         * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  83         *        ---------------------------------
  84         *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  85         *        ---------------------------------
  86         */
  87        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  88                etscfg->tcbwtable[i] = buf[offset++];
  89
  90        /* TSA Assignment Table (8 octets)
  91         * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  92         *        ---------------------------------
  93         *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  94         *        ---------------------------------
  95         */
  96        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  97                etscfg->tsatable[i] = buf[offset++];
  98}
  99
 100/**
 101 * i40e_parse_ieee_etsrec_tlv
 102 * @tlv: IEEE 802.1Qaz ETS REC TLV
 103 * @dcbcfg: Local store to update ETS REC data
 104 *
 105 * Parses IEEE 802.1Qaz ETS REC TLV
 106 **/
 107static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
 108                                       struct i40e_dcbx_config *dcbcfg)
 109{
 110        u8 *buf = tlv->tlvinfo;
 111        u16 offset = 0;
 112        u8 priority;
 113        int i;
 114
 115        /* Move offset to priority table */
 116        offset++;
 117
 118        /* Priority Assignment Table (4 octets)
 119         * Octets:|    1    |    2    |    3    |    4    |
 120         *        -----------------------------------------
 121         *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
 122         *        -----------------------------------------
 123         *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
 124         *        -----------------------------------------
 125         */
 126        for (i = 0; i < 4; i++) {
 127                priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
 128                                I40E_IEEE_ETS_PRIO_1_SHIFT);
 129                dcbcfg->etsrec.prioritytable[i*2] =  priority;
 130                priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
 131                                I40E_IEEE_ETS_PRIO_0_SHIFT);
 132                dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
 133                offset++;
 134        }
 135
 136        /* TC Bandwidth Table (8 octets)
 137         * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 138         *        ---------------------------------
 139         *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 140         *        ---------------------------------
 141         */
 142        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 143                dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
 144
 145        /* TSA Assignment Table (8 octets)
 146         * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 147         *        ---------------------------------
 148         *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 149         *        ---------------------------------
 150         */
 151        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 152                dcbcfg->etsrec.tsatable[i] = buf[offset++];
 153}
 154
 155/**
 156 * i40e_parse_ieee_pfccfg_tlv
 157 * @tlv: IEEE 802.1Qaz PFC CFG TLV
 158 * @dcbcfg: Local store to update PFC CFG data
 159 *
 160 * Parses IEEE 802.1Qaz PFC CFG TLV
 161 **/
 162static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
 163                                       struct i40e_dcbx_config *dcbcfg)
 164{
 165        u8 *buf = tlv->tlvinfo;
 166
 167        /* ----------------------------------------
 168         * |will-|MBC  | Re-  | PFC |  PFC Enable  |
 169         * |ing  |     |served| cap |              |
 170         * -----------------------------------------
 171         * |1bit | 1bit|2 bits|4bits| 1 octet      |
 172         */
 173        dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
 174                                   I40E_IEEE_PFC_WILLING_SHIFT);
 175        dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
 176                               I40E_IEEE_PFC_MBC_SHIFT);
 177        dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
 178                                  I40E_IEEE_PFC_CAP_SHIFT);
 179        dcbcfg->pfc.pfcenable = buf[1];
 180}
 181
 182/**
 183 * i40e_parse_ieee_app_tlv
 184 * @tlv: IEEE 802.1Qaz APP TLV
 185 * @dcbcfg: Local store to update APP PRIO data
 186 *
 187 * Parses IEEE 802.1Qaz APP PRIO TLV
 188 **/
 189static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
 190                                    struct i40e_dcbx_config *dcbcfg)
 191{
 192        u16 typelength;
 193        u16 offset = 0;
 194        u16 length;
 195        int i = 0;
 196        u8 *buf;
 197
 198        typelength = ntohs(tlv->typelength);
 199        length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
 200                       I40E_LLDP_TLV_LEN_SHIFT);
 201        buf = tlv->tlvinfo;
 202
 203        /* The App priority table starts 5 octets after TLV header */
 204        length -= (sizeof(tlv->ouisubtype) + 1);
 205
 206        /* Move offset to App Priority Table */
 207        offset++;
 208
 209        /* Application Priority Table (3 octets)
 210         * Octets:|         1          |    2    |    3    |
 211         *        -----------------------------------------
 212         *        |Priority|Rsrvd| Sel |    Protocol ID    |
 213         *        -----------------------------------------
 214         *   Bits:|23    21|20 19|18 16|15                0|
 215         *        -----------------------------------------
 216         */
 217        while (offset < length) {
 218                dcbcfg->app[i].priority = (u8)((buf[offset] &
 219                                                I40E_IEEE_APP_PRIO_MASK) >>
 220                                               I40E_IEEE_APP_PRIO_SHIFT);
 221                dcbcfg->app[i].selector = (u8)((buf[offset] &
 222                                                I40E_IEEE_APP_SEL_MASK) >>
 223                                               I40E_IEEE_APP_SEL_SHIFT);
 224                dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
 225                                             buf[offset + 2];
 226                /* Move to next app */
 227                offset += 3;
 228                i++;
 229                if (i >= I40E_DCBX_MAX_APPS)
 230                        break;
 231        }
 232
 233        dcbcfg->numapps = i;
 234}
 235
 236/**
 237 * i40e_parse_ieee_tlv
 238 * @tlv: IEEE 802.1Qaz TLV
 239 * @dcbcfg: Local store to update ETS REC data
 240 *
 241 * Get the TLV subtype and send it to parsing function
 242 * based on the subtype value
 243 **/
 244static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
 245                                struct i40e_dcbx_config *dcbcfg)
 246{
 247        u32 ouisubtype;
 248        u8 subtype;
 249
 250        ouisubtype = ntohl(tlv->ouisubtype);
 251        subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
 252                       I40E_LLDP_TLV_SUBTYPE_SHIFT);
 253        switch (subtype) {
 254        case I40E_IEEE_SUBTYPE_ETS_CFG:
 255                i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
 256                break;
 257        case I40E_IEEE_SUBTYPE_ETS_REC:
 258                i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
 259                break;
 260        case I40E_IEEE_SUBTYPE_PFC_CFG:
 261                i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
 262                break;
 263        case I40E_IEEE_SUBTYPE_APP_PRI:
 264                i40e_parse_ieee_app_tlv(tlv, dcbcfg);
 265                break;
 266        default:
 267                break;
 268        }
 269}
 270
 271/**
 272 * i40e_parse_cee_pgcfg_tlv
 273 * @tlv: CEE DCBX PG CFG TLV
 274 * @dcbcfg: Local store to update ETS CFG data
 275 *
 276 * Parses CEE DCBX PG CFG TLV
 277 **/
 278static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
 279                                     struct i40e_dcbx_config *dcbcfg)
 280{
 281        struct i40e_dcb_ets_config *etscfg;
 282        u8 *buf = tlv->tlvinfo;
 283        u16 offset = 0;
 284        u8 priority;
 285        int i;
 286
 287        etscfg = &dcbcfg->etscfg;
 288
 289        if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
 290                etscfg->willing = 1;
 291
 292        etscfg->cbs = 0;
 293        /* Priority Group Table (4 octets)
 294         * Octets:|    1    |    2    |    3    |    4    |
 295         *        -----------------------------------------
 296         *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
 297         *        -----------------------------------------
 298         *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
 299         *        -----------------------------------------
 300         */
 301        for (i = 0; i < 4; i++) {
 302                priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
 303                                 I40E_CEE_PGID_PRIO_1_SHIFT);
 304                etscfg->prioritytable[i * 2] =  priority;
 305                priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
 306                                 I40E_CEE_PGID_PRIO_0_SHIFT);
 307                etscfg->prioritytable[i * 2 + 1] = priority;
 308                offset++;
 309        }
 310
 311        /* PG Percentage Table (8 octets)
 312         * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 313         *        ---------------------------------
 314         *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
 315         *        ---------------------------------
 316         */
 317        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 318                etscfg->tcbwtable[i] = buf[offset++];
 319
 320        /* Number of TCs supported (1 octet) */
 321        etscfg->maxtcs = buf[offset];
 322}
 323
 324/**
 325 * i40e_parse_cee_pfccfg_tlv
 326 * @tlv: CEE DCBX PFC CFG TLV
 327 * @dcbcfg: Local store to update PFC CFG data
 328 *
 329 * Parses CEE DCBX PFC CFG TLV
 330 **/
 331static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
 332                                      struct i40e_dcbx_config *dcbcfg)
 333{
 334        u8 *buf = tlv->tlvinfo;
 335
 336        if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
 337                dcbcfg->pfc.willing = 1;
 338
 339        /* ------------------------
 340         * | PFC Enable | PFC TCs |
 341         * ------------------------
 342         * | 1 octet    | 1 octet |
 343         */
 344        dcbcfg->pfc.pfcenable = buf[0];
 345        dcbcfg->pfc.pfccap = buf[1];
 346}
 347
 348/**
 349 * i40e_parse_cee_app_tlv
 350 * @tlv: CEE DCBX APP TLV
 351 * @dcbcfg: Local store to update APP PRIO data
 352 *
 353 * Parses CEE DCBX APP PRIO TLV
 354 **/
 355static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
 356                                   struct i40e_dcbx_config *dcbcfg)
 357{
 358        u16 length, typelength, offset = 0;
 359        struct i40e_cee_app_prio *app;
 360        u8 i;
 361
 362        typelength = ntohs(tlv->hdr.typelen);
 363        length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
 364                       I40E_LLDP_TLV_LEN_SHIFT);
 365
 366        dcbcfg->numapps = length / sizeof(*app);
 367
 368        if (!dcbcfg->numapps)
 369                return;
 370        if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
 371                dcbcfg->numapps = I40E_DCBX_MAX_APPS;
 372
 373        for (i = 0; i < dcbcfg->numapps; i++) {
 374                u8 up, selector;
 375
 376                app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
 377                for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
 378                        if (app->prio_map & BIT(up))
 379                                break;
 380                }
 381                dcbcfg->app[i].priority = up;
 382
 383                /* Get Selector from lower 2 bits, and convert to IEEE */
 384                selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
 385                switch (selector) {
 386                case I40E_CEE_APP_SEL_ETHTYPE:
 387                        dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
 388                        break;
 389                case I40E_CEE_APP_SEL_TCPIP:
 390                        dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
 391                        break;
 392                default:
 393                        /* Keep selector as it is for unknown types */
 394                        dcbcfg->app[i].selector = selector;
 395                }
 396
 397                dcbcfg->app[i].protocolid = ntohs(app->protocol);
 398                /* Move to next app */
 399                offset += sizeof(*app);
 400        }
 401}
 402
 403/**
 404 * i40e_parse_cee_tlv
 405 * @tlv: CEE DCBX TLV
 406 * @dcbcfg: Local store to update DCBX config data
 407 *
 408 * Get the TLV subtype and send it to parsing function
 409 * based on the subtype value
 410 **/
 411static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
 412                               struct i40e_dcbx_config *dcbcfg)
 413{
 414        u16 len, tlvlen, sublen, typelength;
 415        struct i40e_cee_feat_tlv *sub_tlv;
 416        u8 subtype, feat_tlv_count = 0;
 417        u32 ouisubtype;
 418
 419        ouisubtype = ntohl(tlv->ouisubtype);
 420        subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
 421                       I40E_LLDP_TLV_SUBTYPE_SHIFT);
 422        /* Return if not CEE DCBX */
 423        if (subtype != I40E_CEE_DCBX_TYPE)
 424                return;
 425
 426        typelength = ntohs(tlv->typelength);
 427        tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
 428                        I40E_LLDP_TLV_LEN_SHIFT);
 429        len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
 430              sizeof(struct i40e_cee_ctrl_tlv);
 431        /* Return if no CEE DCBX Feature TLVs */
 432        if (tlvlen <= len)
 433                return;
 434
 435        sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
 436        while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
 437                typelength = ntohs(sub_tlv->hdr.typelen);
 438                sublen = (u16)((typelength &
 439                                I40E_LLDP_TLV_LEN_MASK) >>
 440                                I40E_LLDP_TLV_LEN_SHIFT);
 441                subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
 442                                I40E_LLDP_TLV_TYPE_SHIFT);
 443                switch (subtype) {
 444                case I40E_CEE_SUBTYPE_PG_CFG:
 445                        i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
 446                        break;
 447                case I40E_CEE_SUBTYPE_PFC_CFG:
 448                        i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
 449                        break;
 450                case I40E_CEE_SUBTYPE_APP_PRI:
 451                        i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
 452                        break;
 453                default:
 454                        return; /* Invalid Sub-type return */
 455                }
 456                feat_tlv_count++;
 457                /* Move to next sub TLV */
 458                sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
 459                                                sizeof(sub_tlv->hdr.typelen) +
 460                                                sublen);
 461        }
 462}
 463
 464/**
 465 * i40e_parse_org_tlv
 466 * @tlv: Organization specific TLV
 467 * @dcbcfg: Local store to update ETS REC data
 468 *
 469 * Currently only IEEE 802.1Qaz TLV is supported, all others
 470 * will be returned
 471 **/
 472static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
 473                               struct i40e_dcbx_config *dcbcfg)
 474{
 475        u32 ouisubtype;
 476        u32 oui;
 477
 478        ouisubtype = ntohl(tlv->ouisubtype);
 479        oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
 480                    I40E_LLDP_TLV_OUI_SHIFT);
 481        switch (oui) {
 482        case I40E_IEEE_8021QAZ_OUI:
 483                i40e_parse_ieee_tlv(tlv, dcbcfg);
 484                break;
 485        case I40E_CEE_DCBX_OUI:
 486                i40e_parse_cee_tlv(tlv, dcbcfg);
 487                break;
 488        default:
 489                break;
 490        }
 491}
 492
 493/**
 494 * i40e_lldp_to_dcb_config
 495 * @lldpmib: LLDPDU to be parsed
 496 * @dcbcfg: store for LLDPDU data
 497 *
 498 * Parse DCB configuration from the LLDPDU
 499 **/
 500i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
 501                                    struct i40e_dcbx_config *dcbcfg)
 502{
 503        i40e_status ret = 0;
 504        struct i40e_lldp_org_tlv *tlv;
 505        u16 type;
 506        u16 length;
 507        u16 typelength;
 508        u16 offset = 0;
 509
 510        if (!lldpmib || !dcbcfg)
 511                return I40E_ERR_PARAM;
 512
 513        /* set to the start of LLDPDU */
 514        lldpmib += ETH_HLEN;
 515        tlv = (struct i40e_lldp_org_tlv *)lldpmib;
 516        while (1) {
 517                typelength = ntohs(tlv->typelength);
 518                type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
 519                             I40E_LLDP_TLV_TYPE_SHIFT);
 520                length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
 521                               I40E_LLDP_TLV_LEN_SHIFT);
 522                offset += sizeof(typelength) + length;
 523
 524                /* END TLV or beyond LLDPDU size */
 525                if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
 526                        break;
 527
 528                switch (type) {
 529                case I40E_TLV_TYPE_ORG:
 530                        i40e_parse_org_tlv(tlv, dcbcfg);
 531                        break;
 532                default:
 533                        break;
 534                }
 535
 536                /* Move to next TLV */
 537                tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
 538                                                    sizeof(tlv->typelength) +
 539                                                    length);
 540        }
 541
 542        return ret;
 543}
 544
 545/**
 546 * i40e_aq_get_dcb_config
 547 * @hw: pointer to the hw struct
 548 * @mib_type: mib type for the query
 549 * @bridgetype: bridge type for the query (remote)
 550 * @dcbcfg: store for LLDPDU data
 551 *
 552 * Query DCB configuration from the Firmware
 553 **/
 554i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
 555                                   u8 bridgetype,
 556                                   struct i40e_dcbx_config *dcbcfg)
 557{
 558        i40e_status ret = 0;
 559        struct i40e_virt_mem mem;
 560        u8 *lldpmib;
 561
 562        /* Allocate the LLDPDU */
 563        ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
 564        if (ret)
 565                return ret;
 566
 567        lldpmib = (u8 *)mem.va;
 568        ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
 569                                   (void *)lldpmib, I40E_LLDPDU_SIZE,
 570                                   NULL, NULL, NULL);
 571        if (ret)
 572                goto free_mem;
 573
 574        /* Parse LLDP MIB to get dcb configuration */
 575        ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
 576
 577free_mem:
 578        i40e_free_virt_mem(hw, &mem);
 579        return ret;
 580}
 581
 582/**
 583 * i40e_cee_to_dcb_v1_config
 584 * @cee_cfg: pointer to CEE v1 response configuration struct
 585 * @dcbcfg: DCB configuration struct
 586 *
 587 * Convert CEE v1 configuration from firmware to DCB configuration
 588 **/
 589static void i40e_cee_to_dcb_v1_config(
 590                        struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
 591                        struct i40e_dcbx_config *dcbcfg)
 592{
 593        u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);
 594        u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
 595        u8 i, tc, err;
 596
 597        /* CEE PG data to ETS config */
 598        dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
 599
 600        /* Note that the FW creates the oper_prio_tc nibbles reversed
 601         * from those in the CEE Priority Group sub-TLV.
 602         */
 603        for (i = 0; i < 4; i++) {
 604                tc = (u8)((cee_cfg->oper_prio_tc[i] &
 605                         I40E_CEE_PGID_PRIO_0_MASK) >>
 606                         I40E_CEE_PGID_PRIO_0_SHIFT);
 607                dcbcfg->etscfg.prioritytable[i * 2] =  tc;
 608                tc = (u8)((cee_cfg->oper_prio_tc[i] &
 609                         I40E_CEE_PGID_PRIO_1_MASK) >>
 610                         I40E_CEE_PGID_PRIO_1_SHIFT);
 611                dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
 612        }
 613
 614        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 615                dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
 616
 617        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
 618                if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
 619                        /* Map it to next empty TC */
 620                        dcbcfg->etscfg.prioritytable[i] =
 621                                                cee_cfg->oper_num_tc - 1;
 622                        dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
 623                } else {
 624                        dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
 625                }
 626        }
 627
 628        /* CEE PFC data to ETS config */
 629        dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
 630        dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
 631
 632        status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
 633                  I40E_AQC_CEE_APP_STATUS_SHIFT;
 634        err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
 635        /* Add APPs if Error is False */
 636        if (!err) {
 637                /* CEE operating configuration supports FCoE/iSCSI/FIP only */
 638                dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
 639
 640                /* FCoE APP */
 641                dcbcfg->app[0].priority =
 642                        (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
 643                         I40E_AQC_CEE_APP_FCOE_SHIFT;
 644                dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
 645                dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
 646
 647                /* iSCSI APP */
 648                dcbcfg->app[1].priority =
 649                        (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
 650                         I40E_AQC_CEE_APP_ISCSI_SHIFT;
 651                dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
 652                dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
 653
 654                /* FIP APP */
 655                dcbcfg->app[2].priority =
 656                        (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
 657                         I40E_AQC_CEE_APP_FIP_SHIFT;
 658                dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
 659                dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
 660        }
 661}
 662
 663/**
 664 * i40e_cee_to_dcb_config
 665 * @cee_cfg: pointer to CEE configuration struct
 666 * @dcbcfg: DCB configuration struct
 667 *
 668 * Convert CEE configuration from firmware to DCB configuration
 669 **/
 670static void i40e_cee_to_dcb_config(
 671                                struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
 672                                struct i40e_dcbx_config *dcbcfg)
 673{
 674        u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
 675        u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
 676        u8 i, tc, err, sync, oper;
 677
 678        /* CEE PG data to ETS config */
 679        dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
 680
 681        /* Note that the FW creates the oper_prio_tc nibbles reversed
 682         * from those in the CEE Priority Group sub-TLV.
 683         */
 684        for (i = 0; i < 4; i++) {
 685                tc = (u8)((cee_cfg->oper_prio_tc[i] &
 686                         I40E_CEE_PGID_PRIO_0_MASK) >>
 687                         I40E_CEE_PGID_PRIO_0_SHIFT);
 688                dcbcfg->etscfg.prioritytable[i * 2] =  tc;
 689                tc = (u8)((cee_cfg->oper_prio_tc[i] &
 690                         I40E_CEE_PGID_PRIO_1_MASK) >>
 691                         I40E_CEE_PGID_PRIO_1_SHIFT);
 692                dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
 693        }
 694
 695        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 696                dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
 697
 698        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
 699                if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
 700                        /* Map it to next empty TC */
 701                        dcbcfg->etscfg.prioritytable[i] =
 702                                                cee_cfg->oper_num_tc - 1;
 703                        dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
 704                } else {
 705                        dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
 706                }
 707        }
 708
 709        /* CEE PFC data to ETS config */
 710        dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
 711        dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
 712
 713        i = 0;
 714        status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
 715                  I40E_AQC_CEE_FCOE_STATUS_SHIFT;
 716        err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
 717        sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
 718        oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
 719        /* Add FCoE APP if Error is False and Oper/Sync is True */
 720        if (!err && sync && oper) {
 721                /* FCoE APP */
 722                dcbcfg->app[i].priority =
 723                        (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
 724                         I40E_AQC_CEE_APP_FCOE_SHIFT;
 725                dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
 726                dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
 727                i++;
 728        }
 729
 730        status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
 731                  I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
 732        err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
 733        sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
 734        oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
 735        /* Add iSCSI APP if Error is False and Oper/Sync is True */
 736        if (!err && sync && oper) {
 737                /* iSCSI APP */
 738                dcbcfg->app[i].priority =
 739                        (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
 740                         I40E_AQC_CEE_APP_ISCSI_SHIFT;
 741                dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
 742                dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
 743                i++;
 744        }
 745
 746        status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
 747                  I40E_AQC_CEE_FIP_STATUS_SHIFT;
 748        err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
 749        sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
 750        oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
 751        /* Add FIP APP if Error is False and Oper/Sync is True */
 752        if (!err && sync && oper) {
 753                /* FIP APP */
 754                dcbcfg->app[i].priority =
 755                        (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
 756                         I40E_AQC_CEE_APP_FIP_SHIFT;
 757                dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
 758                dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
 759                i++;
 760        }
 761        dcbcfg->numapps = i;
 762}
 763
 764/**
 765 * i40e_get_ieee_dcb_config
 766 * @hw: pointer to the hw struct
 767 *
 768 * Get IEEE mode DCB configuration from the Firmware
 769 **/
 770static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw)
 771{
 772        i40e_status ret = 0;
 773
 774        /* IEEE mode */
 775        hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
 776        /* Get Local DCB Config */
 777        ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
 778                                     &hw->local_dcbx_config);
 779        if (ret)
 780                goto out;
 781
 782        /* Get Remote DCB Config */
 783        ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
 784                                     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
 785                                     &hw->remote_dcbx_config);
 786        /* Don't treat ENOENT as an error for Remote MIBs */
 787        if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
 788                ret = 0;
 789
 790out:
 791        return ret;
 792}
 793
 794/**
 795 * i40e_get_dcb_config
 796 * @hw: pointer to the hw struct
 797 *
 798 * Get DCB configuration from the Firmware
 799 **/
 800i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
 801{
 802        i40e_status ret = 0;
 803        struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
 804        struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
 805
 806        /* If Firmware version < v4.33 on X710/XL710, IEEE only */
 807        if ((hw->mac.type == I40E_MAC_XL710) &&
 808            (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
 809              (hw->aq.fw_maj_ver < 4)))
 810                return i40e_get_ieee_dcb_config(hw);
 811
 812        /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
 813        if ((hw->mac.type == I40E_MAC_XL710) &&
 814            ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
 815                ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
 816                                                 sizeof(cee_v1_cfg), NULL);
 817                if (!ret) {
 818                        /* CEE mode */
 819                        hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
 820                        hw->local_dcbx_config.tlv_status =
 821                                        le16_to_cpu(cee_v1_cfg.tlv_status);
 822                        i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
 823                                                  &hw->local_dcbx_config);
 824                }
 825        } else {
 826                ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
 827                                                 sizeof(cee_cfg), NULL);
 828                if (!ret) {
 829                        /* CEE mode */
 830                        hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
 831                        hw->local_dcbx_config.tlv_status =
 832                                        le32_to_cpu(cee_cfg.tlv_status);
 833                        i40e_cee_to_dcb_config(&cee_cfg,
 834                                               &hw->local_dcbx_config);
 835                }
 836        }
 837
 838        /* CEE mode not enabled try querying IEEE data */
 839        if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
 840                return i40e_get_ieee_dcb_config(hw);
 841
 842        if (ret)
 843                goto out;
 844
 845        /* Get CEE DCB Desired Config */
 846        ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
 847                                     &hw->desired_dcbx_config);
 848        if (ret)
 849                goto out;
 850
 851        /* Get Remote DCB Config */
 852        ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
 853                                     I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
 854                                     &hw->remote_dcbx_config);
 855        /* Don't treat ENOENT as an error for Remote MIBs */
 856        if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
 857                ret = 0;
 858
 859out:
 860        return ret;
 861}
 862
 863/**
 864 * i40e_init_dcb
 865 * @hw: pointer to the hw struct
 866 * @enable_mib_change: enable mib change event
 867 *
 868 * Update DCB configuration from the Firmware
 869 **/
 870i40e_status i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
 871{
 872        i40e_status ret = 0;
 873        struct i40e_lldp_variables lldp_cfg;
 874        u8 adminstatus = 0;
 875
 876        if (!hw->func_caps.dcb)
 877                return I40E_NOT_SUPPORTED;
 878
 879        /* Read LLDP NVM area */
 880        if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
 881                u8 offset = 0;
 882
 883                if (hw->mac.type == I40E_MAC_XL710)
 884                        offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
 885                else if (hw->mac.type == I40E_MAC_X722)
 886                        offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
 887                else
 888                        return I40E_NOT_SUPPORTED;
 889
 890                ret = i40e_read_nvm_module_data(hw,
 891                                                I40E_SR_EMP_SR_SETTINGS_PTR,
 892                                                offset,
 893                                                I40E_LLDP_CURRENT_STATUS_OFFSET,
 894                                                I40E_LLDP_CURRENT_STATUS_SIZE,
 895                                                &lldp_cfg.adminstatus);
 896        } else {
 897                ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
 898        }
 899        if (ret)
 900                return I40E_ERR_NOT_READY;
 901
 902        /* Get the LLDP AdminStatus for the current port */
 903        adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
 904        adminstatus &= 0xF;
 905
 906        /* LLDP agent disabled */
 907        if (!adminstatus) {
 908                hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
 909                return I40E_ERR_NOT_READY;
 910        }
 911
 912        /* Get DCBX status */
 913        ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
 914        if (ret)
 915                return ret;
 916
 917        /* Check the DCBX Status */
 918        if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
 919            hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
 920                /* Get current DCBX configuration */
 921                ret = i40e_get_dcb_config(hw);
 922                if (ret)
 923                        return ret;
 924        } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
 925                return I40E_ERR_NOT_READY;
 926        }
 927
 928        /* Configure the LLDP MIB change event */
 929        if (enable_mib_change)
 930                ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
 931
 932        return ret;
 933}
 934
 935/**
 936 * i40e_get_fw_lldp_status
 937 * @hw: pointer to the hw struct
 938 * @lldp_status: pointer to the status enum
 939 *
 940 * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
 941 * Status of agent is reported via @lldp_status parameter.
 942 **/
 943enum i40e_status_code
 944i40e_get_fw_lldp_status(struct i40e_hw *hw,
 945                        enum i40e_get_fw_lldp_status_resp *lldp_status)
 946{
 947        struct i40e_virt_mem mem;
 948        i40e_status ret;
 949        u8 *lldpmib;
 950
 951        if (!lldp_status)
 952                return I40E_ERR_PARAM;
 953
 954        /* Allocate buffer for the LLDPDU */
 955        ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
 956        if (ret)
 957                return ret;
 958
 959        lldpmib = (u8 *)mem.va;
 960        ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
 961                                   I40E_LLDPDU_SIZE, NULL, NULL, NULL);
 962
 963        if (!ret) {
 964                *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
 965        } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
 966                /* MIB is not available yet but the agent is running */
 967                *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
 968                ret = 0;
 969        } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
 970                *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
 971                ret = 0;
 972        }
 973
 974        i40e_free_virt_mem(hw, &mem);
 975        return ret;
 976}
 977
 978/**
 979 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
 980 * @tlv: Fill the ETS config data in IEEE format
 981 * @dcbcfg: Local store which holds the DCB Config
 982 *
 983 * Prepare IEEE 802.1Qaz ETS CFG TLV
 984 **/
 985static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
 986                                  struct i40e_dcbx_config *dcbcfg)
 987{
 988        u8 priority0, priority1, maxtcwilling = 0;
 989        struct i40e_dcb_ets_config *etscfg;
 990        u16 offset = 0, typelength, i;
 991        u8 *buf = tlv->tlvinfo;
 992        u32 ouisubtype;
 993
 994        typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
 995                        I40E_IEEE_ETS_TLV_LENGTH);
 996        tlv->typelength = htons(typelength);
 997
 998        ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
 999                        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 **/
1060static 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 **/
1124static 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 **/
1162static 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 **/
1213static 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 **/
1241i40e_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 **/
1277i40e_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 **/
1315void 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 **/
1349void 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 **/
1411void 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 **/
1535void 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 **/
1551u8 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 **/
1569void 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 **/
1597void 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 **/
1628void 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 **/
1705void 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 **/
1891static 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
1942err_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 **/
1953i40e_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}
1988