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

Cache object: 22d0a12b4d8ee8dccd50c92225b5d808


[ 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.