The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ixl/i40e_dcb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /******************************************************************************
    2 
    3   Copyright (c) 2013-2018, Intel Corporation 
    4   All rights reserved.
    5   
    6   Redistribution and use in source and binary forms, with or without 
    7   modification, are permitted provided that the following conditions are met:
    8   
    9    1. Redistributions of source code must retain the above copyright notice, 
   10       this list of conditions and the following disclaimer.
   11   
   12    2. Redistributions in binary form must reproduce the above copyright 
   13       notice, this list of conditions and the following disclaimer in the 
   14       documentation and/or other materials provided with the distribution.
   15   
   16    3. Neither the name of the Intel Corporation nor the names of its 
   17       contributors may be used to endorse or promote products derived from 
   18       this software without specific prior written permission.
   19   
   20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30   POSSIBILITY OF SUCH DAMAGE.
   31 
   32 ******************************************************************************/
   33 /*$FreeBSD$*/
   34 
   35 #include "i40e_adminq.h"
   36 #include "i40e_prototype.h"
   37 #include "i40e_dcb.h"
   38 
   39 /**
   40  * i40e_get_dcbx_status
   41  * @hw: pointer to the hw struct
   42  * @status: Embedded DCBX Engine Status
   43  *
   44  * Get the DCBX status from the Firmware
   45  **/
   46 enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
   47 {
   48         u32 reg;
   49 
   50         if (!status)
   51                 return I40E_ERR_PARAM;
   52 
   53         reg = rd32(hw, I40E_PRTDCB_GENS);
   54         *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
   55                         I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
   56 
   57         return I40E_SUCCESS;
   58 }
   59 
   60 /**
   61  * i40e_parse_ieee_etscfg_tlv
   62  * @tlv: IEEE 802.1Qaz ETS CFG TLV
   63  * @dcbcfg: Local store to update ETS CFG data
   64  *
   65  * Parses IEEE 802.1Qaz ETS CFG TLV
   66  **/
   67 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
   68                                        struct i40e_dcbx_config *dcbcfg)
   69 {
   70         struct i40e_dcb_ets_config *etscfg;
   71         u8 *buf = tlv->tlvinfo;
   72         u16 offset = 0;
   73         u8 priority;
   74         int i;
   75 
   76         /* First Octet post subtype
   77          * --------------------------
   78          * |will-|CBS  | Re-  | Max |
   79          * |ing  |     |served| TCs |
   80          * --------------------------
   81          * |1bit | 1bit|3 bits|3bits|
   82          */
   83         etscfg = &dcbcfg->etscfg;
   84         etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
   85                                I40E_IEEE_ETS_WILLING_SHIFT);
   86         etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
   87                            I40E_IEEE_ETS_CBS_SHIFT);
   88         etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
   89                               I40E_IEEE_ETS_MAXTC_SHIFT);
   90 
   91         /* Move offset to Priority Assignment Table */
   92         offset++;
   93 
   94         /* Priority Assignment Table (4 octets)
   95          * Octets:|    1    |    2    |    3    |    4    |
   96          *        -----------------------------------------
   97          *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
   98          *        -----------------------------------------
   99          *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
  100          *        -----------------------------------------
  101          */
  102         for (i = 0; i < 4; i++) {
  103                 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
  104                                 I40E_IEEE_ETS_PRIO_1_SHIFT);
  105                 etscfg->prioritytable[i * 2] =  priority;
  106                 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
  107                                 I40E_IEEE_ETS_PRIO_0_SHIFT);
  108                 etscfg->prioritytable[i * 2 + 1] = priority;
  109                 offset++;
  110         }
  111 
  112         /* TC Bandwidth Table (8 octets)
  113          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  114          *        ---------------------------------
  115          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  116          *        ---------------------------------
  117          */
  118         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  119                 etscfg->tcbwtable[i] = buf[offset++];
  120 
  121         /* TSA Assignment Table (8 octets)
  122          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  123          *        ---------------------------------
  124          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  125          *        ---------------------------------
  126          */
  127         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  128                 etscfg->tsatable[i] = buf[offset++];
  129 }
  130 
  131 /**
  132  * i40e_parse_ieee_etsrec_tlv
  133  * @tlv: IEEE 802.1Qaz ETS REC TLV
  134  * @dcbcfg: Local store to update ETS REC data
  135  *
  136  * Parses IEEE 802.1Qaz ETS REC TLV
  137  **/
  138 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
  139                                        struct i40e_dcbx_config *dcbcfg)
  140 {
  141         u8 *buf = tlv->tlvinfo;
  142         u16 offset = 0;
  143         u8 priority;
  144         int i;
  145 
  146         /* Move offset to priority table */
  147         offset++;
  148 
  149         /* Priority Assignment Table (4 octets)
  150          * Octets:|    1    |    2    |    3    |    4    |
  151          *        -----------------------------------------
  152          *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  153          *        -----------------------------------------
  154          *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
  155          *        -----------------------------------------
  156          */
  157         for (i = 0; i < 4; i++) {
  158                 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
  159                                 I40E_IEEE_ETS_PRIO_1_SHIFT);
  160                 dcbcfg->etsrec.prioritytable[i*2] =  priority;
  161                 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
  162                                 I40E_IEEE_ETS_PRIO_0_SHIFT);
  163                 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
  164                 offset++;
  165         }
  166 
  167         /* TC Bandwidth Table (8 octets)
  168          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  169          *        ---------------------------------
  170          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  171          *        ---------------------------------
  172          */
  173         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  174                 dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
  175 
  176         /* TSA Assignment Table (8 octets)
  177          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  178          *        ---------------------------------
  179          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  180          *        ---------------------------------
  181          */
  182         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  183                 dcbcfg->etsrec.tsatable[i] = buf[offset++];
  184 }
  185 
  186 /**
  187  * i40e_parse_ieee_pfccfg_tlv
  188  * @tlv: IEEE 802.1Qaz PFC CFG TLV
  189  * @dcbcfg: Local store to update PFC CFG data
  190  *
  191  * Parses IEEE 802.1Qaz PFC CFG TLV
  192  **/
  193 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
  194                                        struct i40e_dcbx_config *dcbcfg)
  195 {
  196         u8 *buf = tlv->tlvinfo;
  197 
  198         /* ----------------------------------------
  199          * |will-|MBC  | Re-  | PFC |  PFC Enable  |
  200          * |ing  |     |served| cap |              |
  201          * -----------------------------------------
  202          * |1bit | 1bit|2 bits|4bits| 1 octet      |
  203          */
  204         dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
  205                                    I40E_IEEE_PFC_WILLING_SHIFT);
  206         dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
  207                                I40E_IEEE_PFC_MBC_SHIFT);
  208         dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
  209                                   I40E_IEEE_PFC_CAP_SHIFT);
  210         dcbcfg->pfc.pfcenable = buf[1];
  211 }
  212 
  213 /**
  214  * i40e_parse_ieee_app_tlv
  215  * @tlv: IEEE 802.1Qaz APP TLV
  216  * @dcbcfg: Local store to update APP PRIO data
  217  *
  218  * Parses IEEE 802.1Qaz APP PRIO TLV
  219  **/
  220 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
  221                                     struct i40e_dcbx_config *dcbcfg)
  222 {
  223         u16 typelength;
  224         u16 offset = 0;
  225         u16 length;
  226         int i = 0;
  227         u8 *buf;
  228 
  229         typelength = I40E_NTOHS(tlv->typelength);
  230         length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
  231                        I40E_LLDP_TLV_LEN_SHIFT);
  232         buf = tlv->tlvinfo;
  233 
  234         /* The App priority table starts 5 octets after TLV header */
  235         length -= (sizeof(tlv->ouisubtype) + 1);
  236 
  237         /* Move offset to App Priority Table */
  238         offset++;
  239 
  240         /* Application Priority Table (3 octets)
  241          * Octets:|         1          |    2    |    3    |
  242          *        -----------------------------------------
  243          *        |Priority|Rsrvd| Sel |    Protocol ID    |
  244          *        -----------------------------------------
  245          *   Bits:|23    21|20 19|18 16|15                0|
  246          *        -----------------------------------------
  247          */
  248         while (offset < length) {
  249                 dcbcfg->app[i].priority = (u8)((buf[offset] &
  250                                                 I40E_IEEE_APP_PRIO_MASK) >>
  251                                                I40E_IEEE_APP_PRIO_SHIFT);
  252                 dcbcfg->app[i].selector = (u8)((buf[offset] &
  253                                                 I40E_IEEE_APP_SEL_MASK) >>
  254                                                I40E_IEEE_APP_SEL_SHIFT);
  255                 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
  256                                              buf[offset + 2];
  257                 /* Move to next app */
  258                 offset += 3;
  259                 i++;
  260                 if (i >= I40E_DCBX_MAX_APPS)
  261                         break;
  262         }
  263 
  264         dcbcfg->numapps = i;
  265 }
  266 
  267 /**
  268  * i40e_parse_ieee_tlv
  269  * @tlv: IEEE 802.1Qaz TLV
  270  * @dcbcfg: Local store to update ETS REC data
  271  *
  272  * Get the TLV subtype and send it to parsing function
  273  * based on the subtype value
  274  **/
  275 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
  276                                 struct i40e_dcbx_config *dcbcfg)
  277 {
  278         u32 ouisubtype;
  279         u8 subtype;
  280 
  281         ouisubtype = I40E_NTOHL(tlv->ouisubtype);
  282         subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
  283                        I40E_LLDP_TLV_SUBTYPE_SHIFT);
  284         switch (subtype) {
  285         case I40E_IEEE_SUBTYPE_ETS_CFG:
  286                 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
  287                 break;
  288         case I40E_IEEE_SUBTYPE_ETS_REC:
  289                 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
  290                 break;
  291         case I40E_IEEE_SUBTYPE_PFC_CFG:
  292                 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
  293                 break;
  294         case I40E_IEEE_SUBTYPE_APP_PRI:
  295                 i40e_parse_ieee_app_tlv(tlv, dcbcfg);
  296                 break;
  297         default:
  298                 break;
  299         }
  300 }
  301 
  302 /**
  303  * i40e_parse_cee_pgcfg_tlv
  304  * @tlv: CEE DCBX PG CFG TLV
  305  * @dcbcfg: Local store to update ETS CFG data
  306  *
  307  * Parses CEE DCBX PG CFG TLV
  308  **/
  309 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
  310                                      struct i40e_dcbx_config *dcbcfg)
  311 {
  312         struct i40e_dcb_ets_config *etscfg;
  313         u8 *buf = tlv->tlvinfo;
  314         u16 offset = 0;
  315         u8 priority;
  316         int i;
  317 
  318         etscfg = &dcbcfg->etscfg;
  319 
  320         if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
  321                 etscfg->willing = 1;
  322 
  323         etscfg->cbs = 0;
  324         /* Priority Group Table (4 octets)
  325          * Octets:|    1    |    2    |    3    |    4    |
  326          *        -----------------------------------------
  327          *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  328          *        -----------------------------------------
  329          *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
  330          *        -----------------------------------------
  331          */
  332         for (i = 0; i < 4; i++) {
  333                 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
  334                                  I40E_CEE_PGID_PRIO_1_SHIFT);
  335                 etscfg->prioritytable[i * 2] =  priority;
  336                 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
  337                                  I40E_CEE_PGID_PRIO_0_SHIFT);
  338                 etscfg->prioritytable[i * 2 + 1] = priority;
  339                 offset++;
  340         }
  341 
  342         /* PG Percentage Table (8 octets)
  343          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  344          *        ---------------------------------
  345          *        |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
  346          *        ---------------------------------
  347          */
  348         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  349                 etscfg->tcbwtable[i] = buf[offset++];
  350 
  351                 if (etscfg->prioritytable[i] == I40E_CEE_PGID_STRICT)
  352                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
  353                 else
  354                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
  355         }
  356 
  357         /* Number of TCs supported (1 octet) */
  358         etscfg->maxtcs = buf[offset];
  359 }
  360 
  361 /**
  362  * i40e_parse_cee_pfccfg_tlv
  363  * @tlv: CEE DCBX PFC CFG TLV
  364  * @dcbcfg: Local store to update PFC CFG data
  365  *
  366  * Parses CEE DCBX PFC CFG TLV
  367  **/
  368 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
  369                                       struct i40e_dcbx_config *dcbcfg)
  370 {
  371         u8 *buf = tlv->tlvinfo;
  372 
  373         if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
  374                 dcbcfg->pfc.willing = 1;
  375 
  376         /* ------------------------
  377          * | PFC Enable | PFC TCs |
  378          * ------------------------
  379          * | 1 octet    | 1 octet |
  380          */
  381         dcbcfg->pfc.pfcenable = buf[0];
  382         dcbcfg->pfc.pfccap = buf[1];
  383 }
  384 
  385 /**
  386  * i40e_parse_cee_app_tlv
  387  * @tlv: CEE DCBX APP TLV
  388  * @dcbcfg: Local store to update APP PRIO data
  389  *
  390  * Parses CEE DCBX APP PRIO TLV
  391  **/
  392 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
  393                                    struct i40e_dcbx_config *dcbcfg)
  394 {
  395         u16 length, typelength, offset = 0;
  396         struct i40e_cee_app_prio *app;
  397         u8 i;
  398 
  399         typelength = I40E_NTOHS(tlv->hdr.typelen);
  400         length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
  401                        I40E_LLDP_TLV_LEN_SHIFT);
  402 
  403         dcbcfg->numapps = length / sizeof(*app);
  404         if (!dcbcfg->numapps)
  405                 return;
  406         if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
  407                 dcbcfg->numapps = I40E_DCBX_MAX_APPS;
  408 
  409         for (i = 0; i < dcbcfg->numapps; i++) {
  410                 u8 up, selector;
  411 
  412                 app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
  413                 for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
  414                         if (app->prio_map & BIT(up))
  415                                 break;
  416                 }
  417                 dcbcfg->app[i].priority = up;
  418 
  419                 /* Get Selector from lower 2 bits, and convert to IEEE */
  420                 selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
  421                 switch (selector) {
  422                 case I40E_CEE_APP_SEL_ETHTYPE:
  423                         dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  424                         break;
  425                 case I40E_CEE_APP_SEL_TCPIP:
  426                         dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
  427                         break;
  428                 default:
  429                         /* Keep selector as it is for unknown types */
  430                         dcbcfg->app[i].selector = selector;
  431                 }
  432 
  433                 dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol);
  434                 /* Move to next app */
  435                 offset += sizeof(*app);
  436         }
  437 }
  438 
  439 /**
  440  * i40e_parse_cee_tlv
  441  * @tlv: CEE DCBX TLV
  442  * @dcbcfg: Local store to update DCBX config data
  443  *
  444  * Get the TLV subtype and send it to parsing function
  445  * based on the subtype value
  446  **/
  447 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
  448                                struct i40e_dcbx_config *dcbcfg)
  449 {
  450         u16 len, tlvlen, sublen, typelength;
  451         struct i40e_cee_feat_tlv *sub_tlv;
  452         u8 subtype, feat_tlv_count = 0;
  453         u32 ouisubtype;
  454 
  455         ouisubtype = I40E_NTOHL(tlv->ouisubtype);
  456         subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
  457                        I40E_LLDP_TLV_SUBTYPE_SHIFT);
  458         /* Return if not CEE DCBX */
  459         if (subtype != I40E_CEE_DCBX_TYPE)
  460                 return;
  461 
  462         typelength = I40E_NTOHS(tlv->typelength);
  463         tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
  464                         I40E_LLDP_TLV_LEN_SHIFT);
  465         len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
  466               sizeof(struct i40e_cee_ctrl_tlv);
  467         /* Return if no CEE DCBX Feature TLVs */
  468         if (tlvlen <= len)
  469                 return;
  470 
  471         sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
  472         while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
  473                 typelength = I40E_NTOHS(sub_tlv->hdr.typelen);
  474                 sublen = (u16)((typelength &
  475                                 I40E_LLDP_TLV_LEN_MASK) >>
  476                                 I40E_LLDP_TLV_LEN_SHIFT);
  477                 subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
  478                                 I40E_LLDP_TLV_TYPE_SHIFT);
  479                 switch (subtype) {
  480                 case I40E_CEE_SUBTYPE_PG_CFG:
  481                         i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
  482                         break;
  483                 case I40E_CEE_SUBTYPE_PFC_CFG:
  484                         i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
  485                         break;
  486                 case I40E_CEE_SUBTYPE_APP_PRI:
  487                         i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
  488                         break;
  489                 default:
  490                         return; /* Invalid Sub-type return */
  491                 }
  492                 feat_tlv_count++;
  493                 /* Move to next sub TLV */
  494                 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
  495                                                 sizeof(sub_tlv->hdr.typelen) +
  496                                                 sublen);
  497         }
  498 }
  499 
  500 /**
  501  * i40e_parse_org_tlv
  502  * @tlv: Organization specific TLV
  503  * @dcbcfg: Local store to update ETS REC data
  504  *
  505  * Currently only IEEE 802.1Qaz TLV is supported, all others
  506  * will be returned
  507  **/
  508 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
  509                                struct i40e_dcbx_config *dcbcfg)
  510 {
  511         u32 ouisubtype;
  512         u32 oui;
  513 
  514         ouisubtype = I40E_NTOHL(tlv->ouisubtype);
  515         oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
  516                     I40E_LLDP_TLV_OUI_SHIFT);
  517         switch (oui) {
  518         case I40E_IEEE_8021QAZ_OUI:
  519                 i40e_parse_ieee_tlv(tlv, dcbcfg);
  520                 break;
  521         case I40E_CEE_DCBX_OUI:
  522                 i40e_parse_cee_tlv(tlv, dcbcfg);
  523                 break;
  524         default:
  525                 break;
  526         }
  527 }
  528 
  529 /**
  530  * i40e_lldp_to_dcb_config
  531  * @lldpmib: LLDPDU to be parsed
  532  * @dcbcfg: store for LLDPDU data
  533  *
  534  * Parse DCB configuration from the LLDPDU
  535  **/
  536 enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
  537                                     struct i40e_dcbx_config *dcbcfg)
  538 {
  539         enum i40e_status_code ret = I40E_SUCCESS;
  540         struct i40e_lldp_org_tlv *tlv;
  541         u16 type;
  542         u16 length;
  543         u16 typelength;
  544         u16 offset = 0;
  545 
  546         if (!lldpmib || !dcbcfg)
  547                 return I40E_ERR_PARAM;
  548 
  549         /* set to the start of LLDPDU */
  550         lldpmib += I40E_LLDP_MIB_HLEN;
  551         tlv = (struct i40e_lldp_org_tlv *)lldpmib;
  552         while (1) {
  553                 typelength = I40E_NTOHS(tlv->typelength);
  554                 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
  555                              I40E_LLDP_TLV_TYPE_SHIFT);
  556                 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
  557                                I40E_LLDP_TLV_LEN_SHIFT);
  558                 offset += sizeof(typelength) + length;
  559 
  560                 /* END TLV or beyond LLDPDU size */
  561                 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
  562                         break;
  563 
  564                 switch (type) {
  565                 case I40E_TLV_TYPE_ORG:
  566                         i40e_parse_org_tlv(tlv, dcbcfg);
  567                         break;
  568                 default:
  569                         break;
  570                 }
  571 
  572                 /* Move to next TLV */
  573                 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
  574                                                     sizeof(tlv->typelength) +
  575                                                     length);
  576         }
  577 
  578         return ret;
  579 }
  580 
  581 /**
  582  * i40e_aq_get_dcb_config
  583  * @hw: pointer to the hw struct
  584  * @mib_type: mib type for the query
  585  * @bridgetype: bridge type for the query (remote)
  586  * @dcbcfg: store for LLDPDU data
  587  *
  588  * Query DCB configuration from the Firmware
  589  **/
  590 enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
  591                                    u8 bridgetype,
  592                                    struct i40e_dcbx_config *dcbcfg)
  593 {
  594         enum i40e_status_code ret = I40E_SUCCESS;
  595         struct i40e_virt_mem mem;
  596         u8 *lldpmib;
  597 
  598         /* Allocate the LLDPDU */
  599         ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
  600         if (ret)
  601                 return ret;
  602 
  603         lldpmib = (u8 *)mem.va;
  604         ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
  605                                    (void *)lldpmib, I40E_LLDPDU_SIZE,
  606                                    NULL, NULL, NULL);
  607         if (ret)
  608                 goto free_mem;
  609 
  610         /* Parse LLDP MIB to get dcb configuration */
  611         ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
  612 
  613 free_mem:
  614         i40e_free_virt_mem(hw, &mem);
  615         return ret;
  616 }
  617 
  618 /**
  619  * i40e_cee_to_dcb_v1_config
  620  * @cee_cfg: pointer to CEE v1 response configuration struct
  621  * @dcbcfg: DCB configuration struct
  622  *
  623  * Convert CEE v1 configuration from firmware to DCB configuration
  624  **/
  625 static void i40e_cee_to_dcb_v1_config(
  626                         struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
  627                         struct i40e_dcbx_config *dcbcfg)
  628 {
  629         u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
  630         u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
  631         u8 i, tc, err;
  632 
  633         /* CEE PG data to ETS config */
  634         dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
  635 
  636         /* Note that the FW creates the oper_prio_tc nibbles reversed
  637          * from those in the CEE Priority Group sub-TLV.
  638          */
  639         for (i = 0; i < 4; i++) {
  640                 tc = (u8)((cee_cfg->oper_prio_tc[i] &
  641                          I40E_CEE_PGID_PRIO_0_MASK) >>
  642                          I40E_CEE_PGID_PRIO_0_SHIFT);
  643                 dcbcfg->etscfg.prioritytable[i*2] =  tc;
  644                 tc = (u8)((cee_cfg->oper_prio_tc[i] &
  645                          I40E_CEE_PGID_PRIO_1_MASK) >>
  646                          I40E_CEE_PGID_PRIO_1_SHIFT);
  647                 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
  648         }
  649 
  650         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  651                 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
  652 
  653         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  654                 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
  655                         /* Map it to next empty TC */
  656                         dcbcfg->etscfg.prioritytable[i] =
  657                                                 cee_cfg->oper_num_tc - 1;
  658                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
  659                 } else {
  660                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
  661                 }
  662         }
  663 
  664         /* CEE PFC data to ETS config */
  665         dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
  666         dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
  667 
  668         status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
  669                   I40E_AQC_CEE_APP_STATUS_SHIFT;
  670         err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  671         /* Add APPs if Error is False */
  672         if (!err) {
  673                 /* CEE operating configuration supports FCoE/iSCSI/FIP only */
  674                 dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
  675 
  676                 /* FCoE APP */
  677                 dcbcfg->app[0].priority =
  678                         (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
  679                          I40E_AQC_CEE_APP_FCOE_SHIFT;
  680                 dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
  681                 dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
  682 
  683                 /* iSCSI APP */
  684                 dcbcfg->app[1].priority =
  685                         (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
  686                          I40E_AQC_CEE_APP_ISCSI_SHIFT;
  687                 dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
  688                 dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
  689 
  690                 /* FIP APP */
  691                 dcbcfg->app[2].priority =
  692                         (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
  693                          I40E_AQC_CEE_APP_FIP_SHIFT;
  694                 dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
  695                 dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
  696         }
  697 }
  698 
  699 /**
  700  * i40e_cee_to_dcb_config
  701  * @cee_cfg: pointer to CEE configuration struct
  702  * @dcbcfg: DCB configuration struct
  703  *
  704  * Convert CEE configuration from firmware to DCB configuration
  705  **/
  706 static void i40e_cee_to_dcb_config(
  707                                 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
  708                                 struct i40e_dcbx_config *dcbcfg)
  709 {
  710         u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
  711         u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
  712         u8 i, tc, err, sync, oper;
  713 
  714         /* CEE PG data to ETS config */
  715         dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
  716 
  717         /* Note that the FW creates the oper_prio_tc nibbles reversed
  718          * from those in the CEE Priority Group sub-TLV.
  719          */
  720         for (i = 0; i < 4; i++) {
  721                 tc = (u8)((cee_cfg->oper_prio_tc[i] &
  722                          I40E_CEE_PGID_PRIO_0_MASK) >>
  723                          I40E_CEE_PGID_PRIO_0_SHIFT);
  724                 dcbcfg->etscfg.prioritytable[i*2] =  tc;
  725                 tc = (u8)((cee_cfg->oper_prio_tc[i] &
  726                          I40E_CEE_PGID_PRIO_1_MASK) >>
  727                          I40E_CEE_PGID_PRIO_1_SHIFT);
  728                 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
  729         }
  730 
  731         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  732                 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
  733 
  734         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  735                 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
  736                         /* Map it to next empty TC */
  737                         dcbcfg->etscfg.prioritytable[i] =
  738                                                 cee_cfg->oper_num_tc - 1;
  739                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
  740                 } else {
  741                         dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
  742                 }
  743         }
  744 
  745         /* CEE PFC data to ETS config */
  746         dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
  747         dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
  748 
  749         i = 0;
  750         status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
  751                   I40E_AQC_CEE_FCOE_STATUS_SHIFT;
  752         err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  753         sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  754         oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  755         /* Add FCoE APP if Error is False and Oper/Sync is True */
  756         if (!err && sync && oper) {
  757                 /* FCoE APP */
  758                 dcbcfg->app[i].priority =
  759                         (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
  760                          I40E_AQC_CEE_APP_FCOE_SHIFT;
  761                 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  762                 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
  763                 i++;
  764         }
  765 
  766         status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
  767                   I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
  768         err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  769         sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  770         oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  771         /* Add iSCSI APP if Error is False and Oper/Sync is True */
  772         if (!err && sync && oper) {
  773                 /* iSCSI APP */
  774                 dcbcfg->app[i].priority =
  775                         (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
  776                          I40E_AQC_CEE_APP_ISCSI_SHIFT;
  777                 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
  778                 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
  779                 i++;
  780         }
  781 
  782         status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
  783                   I40E_AQC_CEE_FIP_STATUS_SHIFT;
  784         err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  785         sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  786         oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  787         /* Add FIP APP if Error is False and Oper/Sync is True */
  788         if (!err && sync && oper) {
  789                 /* FIP APP */
  790                 dcbcfg->app[i].priority =
  791                         (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
  792                          I40E_AQC_CEE_APP_FIP_SHIFT;
  793                 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  794                 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
  795                 i++;
  796         }
  797         dcbcfg->numapps = i;
  798 }
  799 
  800 /**
  801  * i40e_get_ieee_dcb_config
  802  * @hw: pointer to the hw struct
  803  *
  804  * Get IEEE mode DCB configuration from the Firmware
  805  **/
  806 static enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw)
  807 {
  808         enum i40e_status_code ret = I40E_SUCCESS;
  809 
  810         /* IEEE mode */
  811         hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
  812         /* Get Local DCB Config */
  813         ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
  814                                      &hw->local_dcbx_config);
  815         if (ret)
  816                 goto out;
  817 
  818         /* Get Remote DCB Config */
  819         ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
  820                                      I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
  821                                      &hw->remote_dcbx_config);
  822         /* Don't treat ENOENT as an error for Remote MIBs */
  823         if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  824                 ret = I40E_SUCCESS;
  825 
  826 out:
  827         return ret;
  828 }
  829 
  830 /**
  831  * i40e_get_dcb_config
  832  * @hw: pointer to the hw struct
  833  *
  834  * Get DCB configuration from the Firmware
  835  **/
  836 enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
  837 {
  838         enum i40e_status_code ret = I40E_SUCCESS;
  839         struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
  840         struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
  841 
  842         /* If Firmware version < v4.33 on X710/XL710, IEEE only */
  843         if ((hw->mac.type == I40E_MAC_XL710) &&
  844             (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
  845               (hw->aq.fw_maj_ver < 4)))
  846                 return i40e_get_ieee_dcb_config(hw);
  847 
  848         /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
  849         if ((hw->mac.type == I40E_MAC_XL710) &&
  850             ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
  851                 ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
  852                                                  sizeof(cee_v1_cfg), NULL);
  853                 if (ret == I40E_SUCCESS) {
  854                         /* CEE mode */
  855                         hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
  856                         hw->local_dcbx_config.tlv_status =
  857                                         LE16_TO_CPU(cee_v1_cfg.tlv_status);
  858                         i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
  859                                                   &hw->local_dcbx_config);
  860                 }
  861         } else {
  862                 ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
  863                                                  sizeof(cee_cfg), NULL);
  864                 if (ret == I40E_SUCCESS) {
  865                         /* CEE mode */
  866                         hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
  867                         hw->local_dcbx_config.tlv_status =
  868                                         LE32_TO_CPU(cee_cfg.tlv_status);
  869                         i40e_cee_to_dcb_config(&cee_cfg,
  870                                                &hw->local_dcbx_config);
  871                 }
  872         }
  873 
  874         /* CEE mode not enabled try querying IEEE data */
  875         if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  876                 return i40e_get_ieee_dcb_config(hw);
  877 
  878         if (ret != I40E_SUCCESS)
  879                 goto out;
  880 
  881         /* Get CEE DCB Desired Config */
  882         ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
  883                                      &hw->desired_dcbx_config);
  884         if (ret)
  885                 goto out;
  886 
  887         /* Get Remote DCB Config */
  888         ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
  889                              I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
  890                              &hw->remote_dcbx_config);
  891         /* Don't treat ENOENT as an error for Remote MIBs */
  892         if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  893                 ret = I40E_SUCCESS;
  894 
  895 out:
  896         return ret;
  897 }
  898 
  899 /**
  900  * i40e_init_dcb
  901  * @hw: pointer to the hw struct
  902  * @enable_mib_change: enable mib change event
  903  *
  904  * Update DCB configuration from the Firmware
  905  **/
  906 enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
  907 {
  908         enum i40e_status_code ret = I40E_SUCCESS;
  909         struct i40e_lldp_variables lldp_cfg;
  910         u8 adminstatus = 0;
  911 
  912         if (!hw->func_caps.dcb)
  913                 return I40E_NOT_SUPPORTED;
  914 
  915         /* Read LLDP NVM area */
  916         if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
  917                 u8 offset = 0;
  918 
  919                 if (hw->mac.type == I40E_MAC_XL710)
  920                         offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
  921                 else if (hw->mac.type == I40E_MAC_X722)
  922                         offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
  923                 else
  924                         return I40E_NOT_SUPPORTED;
  925 
  926                 ret = i40e_read_nvm_module_data(hw,
  927                                                 I40E_SR_EMP_SR_SETTINGS_PTR,
  928                                                 offset,
  929                                                 I40E_LLDP_CURRENT_STATUS_OFFSET,
  930                                                 I40E_LLDP_CURRENT_STATUS_SIZE,
  931                                                 &lldp_cfg.adminstatus);
  932         } else {
  933                 ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
  934         }
  935         if (ret)
  936                 return I40E_ERR_NOT_READY;
  937 
  938         /* Get the LLDP AdminStatus for the current port */
  939         adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
  940         adminstatus &= 0xF;
  941 
  942         /* LLDP agent disabled */
  943         if (!adminstatus) {
  944                 hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
  945                 return I40E_ERR_NOT_READY;
  946         }
  947 
  948         /* Get DCBX status */
  949         ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
  950         if (ret)
  951                 return ret;
  952 
  953         /* Check the DCBX Status */
  954         if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
  955             hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
  956                 /* Get current DCBX configuration */
  957                 ret = i40e_get_dcb_config(hw);
  958                 if (ret)
  959                         return ret;
  960         } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
  961                 return I40E_ERR_NOT_READY;
  962         }
  963 
  964         /* Configure the LLDP MIB change event */
  965         if (enable_mib_change)
  966                 ret = i40e_aq_cfg_lldp_mib_change_event(hw, TRUE, NULL);
  967 
  968         return ret;
  969 }
  970 
  971 /**
  972  * i40e_get_fw_lldp_status
  973  * @hw: pointer to the hw struct
  974  * @lldp_status: pointer to the status enum
  975  *
  976  * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
  977  * Status of agent is reported via @lldp_status parameter.
  978  **/
  979 enum i40e_status_code
  980 i40e_get_fw_lldp_status(struct i40e_hw *hw,
  981                         enum i40e_get_fw_lldp_status_resp *lldp_status)
  982 {
  983         enum i40e_status_code ret;
  984         struct i40e_virt_mem mem;
  985         u8 *lldpmib;
  986 
  987         if (!lldp_status)
  988                 return I40E_ERR_PARAM;
  989 
  990         /* Allocate buffer for the LLDPDU */
  991         ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
  992         if (ret)
  993                 return ret;
  994 
  995         lldpmib = (u8 *)mem.va;
  996         ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
  997                                    I40E_LLDPDU_SIZE, NULL, NULL, NULL);
  998 
  999         if (ret == I40E_SUCCESS) {
 1000                 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
 1001         } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
 1002                 /* MIB is not available yet but the agent is running */
 1003                 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
 1004                 ret = I40E_SUCCESS;
 1005         } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
 1006                 *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
 1007                 ret = I40E_SUCCESS;
 1008         }
 1009 
 1010         i40e_free_virt_mem(hw, &mem);
 1011         return ret;
 1012 }
 1013 
 1014 
 1015 /**
 1016  * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
 1017  * @tlv: Fill the ETS config data in IEEE format
 1018  * @dcbcfg: Local store which holds the DCB Config
 1019  *
 1020  * Prepare IEEE 802.1Qaz ETS CFG TLV
 1021  **/
 1022 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
 1023                                   struct i40e_dcbx_config *dcbcfg)
 1024 {
 1025         u8 priority0, priority1, maxtcwilling = 0;
 1026         struct i40e_dcb_ets_config *etscfg;
 1027         u16 offset = 0, typelength, i;
 1028         u8 *buf = tlv->tlvinfo;
 1029         u32 ouisubtype;
 1030 
 1031         typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
 1032                         I40E_IEEE_ETS_TLV_LENGTH);
 1033         tlv->typelength = I40E_HTONS(typelength);
 1034 
 1035         ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
 1036                         I40E_IEEE_SUBTYPE_ETS_CFG);
 1037         tlv->ouisubtype = I40E_HTONL(ouisubtype);
 1038 
 1039         /* First Octet post subtype
 1040          * --------------------------
 1041          * |will-|CBS  | Re-  | Max |
 1042          * |ing  |     |served| TCs |
 1043          * --------------------------
 1044          * |1bit | 1bit|3 bits|3bits|
 1045          */
 1046         etscfg = &dcbcfg->etscfg;
 1047         if (etscfg->willing)
 1048                 maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
 1049         maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
 1050         buf[offset] = maxtcwilling;
 1051 
 1052         /* Move offset to Priority Assignment Table */
 1053         offset++;
 1054 
 1055         /* Priority Assignment Table (4 octets)
 1056          * Octets:|    1    |    2    |    3    |    4    |
 1057          *        -----------------------------------------
 1058          *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
 1059          *        -----------------------------------------
 1060          *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
 1061          *        -----------------------------------------
 1062          */
 1063         for (i = 0; i < 4; i++) {
 1064                 priority0 = etscfg->prioritytable[i * 2] & 0xF;
 1065                 priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
 1066                 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
 1067                                 priority1;
 1068                 offset++;
 1069         }
 1070 
 1071         /* TC Bandwidth Table (8 octets)
 1072          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 1073          *        ---------------------------------
 1074          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 1075          *        ---------------------------------
 1076          */
 1077         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 1078                 buf[offset++] = etscfg->tcbwtable[i];
 1079 
 1080         /* TSA Assignment Table (8 octets)
 1081          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 1082          *        ---------------------------------
 1083          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 1084          *        ---------------------------------
 1085          */
 1086         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 1087                 buf[offset++] = etscfg->tsatable[i];
 1088 }
 1089 
 1090 /**
 1091  * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
 1092  * @tlv: Fill ETS Recommended TLV in IEEE format
 1093  * @dcbcfg: Local store which holds the DCB Config
 1094  *
 1095  * Prepare IEEE 802.1Qaz ETS REC TLV
 1096  **/
 1097 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
 1098                                      struct i40e_dcbx_config *dcbcfg)
 1099 {
 1100         struct i40e_dcb_ets_config *etsrec;
 1101         u16 offset = 0, typelength, i;
 1102         u8 priority0, priority1;
 1103         u8 *buf = tlv->tlvinfo;
 1104         u32 ouisubtype;
 1105 
 1106         typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
 1107                         I40E_IEEE_ETS_TLV_LENGTH);
 1108         tlv->typelength = I40E_HTONS(typelength);
 1109 
 1110         ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
 1111                         I40E_IEEE_SUBTYPE_ETS_REC);
 1112         tlv->ouisubtype = I40E_HTONL(ouisubtype);
 1113 
 1114         etsrec = &dcbcfg->etsrec;
 1115         /* First Octet is reserved */
 1116         /* Move offset to Priority Assignment Table */
 1117         offset++;
 1118 
 1119         /* Priority Assignment Table (4 octets)
 1120          * Octets:|    1    |    2    |    3    |    4    |
 1121          *        -----------------------------------------
 1122          *        |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
 1123          *        -----------------------------------------
 1124          *   Bits:|7  4|3  0|7  4|3  0|7  4|3  0|7  4|3  0|
 1125          *        -----------------------------------------
 1126          */
 1127         for (i = 0; i < 4; i++) {
 1128                 priority0 = etsrec->prioritytable[i * 2] & 0xF;
 1129                 priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
 1130                 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
 1131                                 priority1;
 1132                 offset++;
 1133         }
 1134 
 1135         /* TC Bandwidth Table (8 octets)
 1136          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 1137          *        ---------------------------------
 1138          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 1139          *        ---------------------------------
 1140          */
 1141         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 1142                 buf[offset++] = etsrec->tcbwtable[i];
 1143 
 1144         /* TSA Assignment Table (8 octets)
 1145          * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
 1146          *        ---------------------------------
 1147          *        |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
 1148          *        ---------------------------------
 1149          */
 1150         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
 1151                 buf[offset++] = etsrec->tsatable[i];
 1152 }
 1153 
 1154  /**
 1155  * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
 1156  * @tlv: Fill PFC TLV in IEEE format
 1157  * @dcbcfg: Local store to get PFC CFG data
 1158  *
 1159  * Prepare IEEE 802.1Qaz PFC CFG TLV
 1160  **/
 1161 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
 1162                                   struct i40e_dcbx_config *dcbcfg)
 1163 {
 1164         u8 *buf = tlv->tlvinfo;
 1165         u32 ouisubtype;
 1166         u16 typelength;
 1167 
 1168         typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
 1169                         I40E_IEEE_PFC_TLV_LENGTH);
 1170         tlv->typelength = I40E_HTONS(typelength);
 1171 
 1172         ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
 1173                         I40E_IEEE_SUBTYPE_PFC_CFG);
 1174         tlv->ouisubtype = I40E_HTONL(ouisubtype);
 1175 
 1176         /* ----------------------------------------
 1177          * |will-|MBC  | Re-  | PFC |  PFC Enable  |
 1178          * |ing  |     |served| cap |              |
 1179          * -----------------------------------------
 1180          * |1bit | 1bit|2 bits|4bits| 1 octet      |
 1181          */
 1182         if (dcbcfg->pfc.willing)
 1183                 buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
 1184 
 1185         if (dcbcfg->pfc.mbc)
 1186                 buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
 1187 
 1188         buf[0] |= dcbcfg->pfc.pfccap & 0xF;
 1189         buf[1] = dcbcfg->pfc.pfcenable;
 1190 }
 1191 
 1192 /**
 1193  * i40e_add_ieee_app_pri_tlv -  Prepare APP TLV in IEEE format
 1194  * @tlv: Fill APP TLV in IEEE format
 1195  * @dcbcfg: Local store to get APP CFG data
 1196  *
 1197  * Prepare IEEE 802.1Qaz APP CFG TLV
 1198  **/
 1199 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
 1200                                       struct i40e_dcbx_config *dcbcfg)
 1201 {
 1202         u16 typelength, length, offset = 0;
 1203         u8 priority, selector, i = 0;
 1204         u8 *buf = tlv->tlvinfo;
 1205         u32 ouisubtype;
 1206 
 1207         /* No APP TLVs then just return */
 1208         if (dcbcfg->numapps == 0)
 1209                 return;
 1210         ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
 1211                         I40E_IEEE_SUBTYPE_APP_PRI);
 1212         tlv->ouisubtype = I40E_HTONL(ouisubtype);
 1213 
 1214         /* Move offset to App Priority Table */
 1215         offset++;
 1216         /* Application Priority Table (3 octets)
 1217          * Octets:|         1          |    2    |    3    |
 1218          *        -----------------------------------------
 1219          *        |Priority|Rsrvd| Sel |    Protocol ID    |
 1220          *        -----------------------------------------
 1221          *   Bits:|23    21|20 19|18 16|15                0|
 1222          *        -----------------------------------------
 1223          */
 1224         while (i < dcbcfg->numapps) {
 1225                 priority = dcbcfg->app[i].priority & 0x7;
 1226                 selector = dcbcfg->app[i].selector & 0x7;
 1227                 buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
 1228                 buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
 1229                 buf[offset + 2] =  dcbcfg->app[i].protocolid & 0xFF;
 1230                 /* Move to next app */
 1231                 offset += 3;
 1232                 i++;
 1233                 if (i >= I40E_DCBX_MAX_APPS)
 1234                         break;
 1235         }
 1236         /* length includes size of ouisubtype + 1 reserved + 3*numapps */
 1237         length = sizeof(tlv->ouisubtype) + 1 + (i*3);
 1238         typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
 1239                 (length & 0x1FF));
 1240         tlv->typelength = I40E_HTONS(typelength);
 1241 }
 1242 
 1243  /**
 1244  * i40e_add_dcb_tlv - Add all IEEE TLVs
 1245  * @tlv: pointer to org tlv
 1246  *
 1247  * add tlv information
 1248  **/
 1249 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
 1250                              struct i40e_dcbx_config *dcbcfg,
 1251                              u16 tlvid)
 1252 {
 1253         switch (tlvid) {
 1254         case I40E_IEEE_TLV_ID_ETS_CFG:
 1255                 i40e_add_ieee_ets_tlv(tlv, dcbcfg);
 1256                 break;
 1257         case I40E_IEEE_TLV_ID_ETS_REC:
 1258                 i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
 1259                 break;
 1260         case I40E_IEEE_TLV_ID_PFC_CFG:
 1261                 i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
 1262                 break;
 1263         case I40E_IEEE_TLV_ID_APP_PRI:
 1264                 i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
 1265                 break;
 1266         default:
 1267                 break;
 1268         }
 1269 }
 1270 
 1271  /**
 1272  * i40e_set_dcb_config - Set the local LLDP MIB to FW
 1273  * @hw: pointer to the hw struct
 1274  *
 1275  * Set DCB configuration to the Firmware
 1276  **/
 1277 enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
 1278 {
 1279         enum i40e_status_code ret = I40E_SUCCESS;
 1280         struct i40e_dcbx_config *dcbcfg;
 1281         struct i40e_virt_mem mem;
 1282         u8 mib_type, *lldpmib;
 1283         u16 miblen;
 1284 
 1285         /* update the hw local config */
 1286         dcbcfg = &hw->local_dcbx_config;
 1287         /* Allocate the LLDPDU */
 1288         ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
 1289         if (ret)
 1290                 return ret;
 1291 
 1292         mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
 1293         if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
 1294                 mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
 1295                             SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
 1296         }
 1297         lldpmib = (u8 *)mem.va;
 1298         ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
 1299         ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
 1300 
 1301         i40e_free_virt_mem(hw, &mem);
 1302         return ret;
 1303 }
 1304 
 1305 /**
 1306  * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
 1307  * @lldpmib: pointer to mib to be output
 1308  * @miblen: pointer to u16 for length of lldpmib
 1309  * @dcbcfg: store for LLDPDU data
 1310  *
 1311  * send DCB configuration to FW
 1312  **/
 1313 enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
 1314                                               struct i40e_dcbx_config *dcbcfg)
 1315 {
 1316         u16 length, offset = 0, tlvid = I40E_TLV_ID_START;
 1317         enum i40e_status_code ret = I40E_SUCCESS;
 1318         struct i40e_lldp_org_tlv *tlv;
 1319         u16 typelength;
 1320 
 1321         tlv = (struct i40e_lldp_org_tlv *)lldpmib;
 1322         while (1) {
 1323                 i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
 1324                 typelength = I40E_NTOHS(tlv->typelength);
 1325                 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
 1326                                 I40E_LLDP_TLV_LEN_SHIFT);
 1327                 if (length)
 1328                         offset += length + 2;
 1329                 /* END TLV or beyond LLDPDU size */
 1330                 if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) ||
 1331                     (offset > I40E_LLDPDU_SIZE))
 1332                         break;
 1333                 /* Move to next TLV */
 1334                 if (length)
 1335                         tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
 1336                               sizeof(tlv->typelength) + length);
 1337         }
 1338         *miblen = offset;
 1339         return ret;
 1340 }
 1341 
 1342 
 1343 /**
 1344  * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
 1345  * @hw: pointer to the HW structure
 1346  * @lldp_cfg: pointer to hold lldp configuration variables
 1347  * @module: address of the module pointer
 1348  * @word_offset: offset of LLDP configuration
 1349  *
 1350  * Reads the LLDP configuration data from NVM using passed addresses
 1351  **/
 1352 static enum i40e_status_code _i40e_read_lldp_cfg(struct i40e_hw *hw,
 1353                                           struct i40e_lldp_variables *lldp_cfg,
 1354                                           u8 module, u32 word_offset)
 1355 {
 1356         u32 address, offset = (2 * word_offset);
 1357         enum i40e_status_code ret;
 1358         __le16 raw_mem;
 1359         u16 mem;
 1360 
 1361         ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
 1362         if (ret != I40E_SUCCESS)
 1363                 return ret;
 1364 
 1365         ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
 1366                                TRUE, NULL);
 1367         i40e_release_nvm(hw);
 1368         if (ret != I40E_SUCCESS)
 1369                 return ret;
 1370 
 1371         mem = LE16_TO_CPU(raw_mem);
 1372         /* Check if this pointer needs to be read in word size or 4K sector
 1373          * units.
 1374          */
 1375         if (mem & I40E_PTR_TYPE)
 1376                 address = (0x7FFF & mem) * 4096;
 1377         else
 1378                 address = (0x7FFF & mem) * 2;
 1379 
 1380         ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
 1381         if (ret != I40E_SUCCESS)
 1382                 goto err_lldp_cfg;
 1383 
 1384         ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
 1385                                TRUE, NULL);
 1386         i40e_release_nvm(hw);
 1387         if (ret != I40E_SUCCESS)
 1388                 return ret;
 1389 
 1390         mem = LE16_TO_CPU(raw_mem);
 1391         offset = mem + word_offset;
 1392         offset *= 2;
 1393 
 1394         ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
 1395         if (ret != I40E_SUCCESS)
 1396                 goto err_lldp_cfg;
 1397 
 1398         ret = i40e_aq_read_nvm(hw, 0, address + offset,
 1399                                sizeof(struct i40e_lldp_variables), lldp_cfg,
 1400                                TRUE, NULL);
 1401         i40e_release_nvm(hw);
 1402 
 1403 err_lldp_cfg:
 1404         return ret;
 1405 }
 1406 
 1407 /**
 1408  * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
 1409  * @hw: pointer to the HW structure
 1410  * @lldp_cfg: pointer to hold lldp configuration variables
 1411  *
 1412  * Reads the LLDP configuration data from NVM
 1413  **/
 1414 enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
 1415                                          struct i40e_lldp_variables *lldp_cfg)
 1416 {
 1417         enum i40e_status_code ret = I40E_SUCCESS;
 1418         u32 mem;
 1419 
 1420         if (!lldp_cfg)
 1421                 return I40E_ERR_PARAM;
 1422 
 1423         ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
 1424         if (ret != I40E_SUCCESS)
 1425                 return ret;
 1426 
 1427         ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
 1428                                &mem, TRUE, NULL);
 1429         i40e_release_nvm(hw);
 1430         if (ret != I40E_SUCCESS)
 1431                 return ret;
 1432 
 1433         /* Read a bit that holds information whether we are running flat or
 1434          * structured NVM image. Flat image has LLDP configuration in shadow
 1435          * ram, so there is a need to pass different addresses for both cases.
 1436          */
 1437         if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
 1438                 /* Flat NVM case */
 1439                 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
 1440                                           I40E_SR_LLDP_CFG_PTR);
 1441         } else {
 1442                 /* Good old structured NVM image */
 1443                 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
 1444                                           I40E_NVM_LLDP_CFG_PTR);
 1445         }
 1446 
 1447         return ret;
 1448 }

Cache object: d467a9d47796c1ea827233962e7dc6a1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.