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_switch.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_switch.h"
   34 #include "ice_flex_type.h"
   35 #include "ice_flow.h"
   36 
   37 #define ICE_ETH_DA_OFFSET               0
   38 #define ICE_ETH_ETHTYPE_OFFSET          12
   39 #define ICE_ETH_VLAN_TCI_OFFSET         14
   40 #define ICE_MAX_VLAN_ID                 0xFFF
   41 #define ICE_IPV6_ETHER_ID               0x86DD
   42 #define ICE_ETH_P_8021Q                 0x8100
   43 
   44 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
   45  * struct to configure any switch filter rules.
   46  * {DA (6 bytes), SA(6 bytes),
   47  * Ether type (2 bytes for header without VLAN tag) OR
   48  * VLAN tag (4 bytes for header with VLAN tag) }
   49  *
   50  * Word on Hardcoded values
   51  * byte 0 = 0x2: to identify it as locally administered DA MAC
   52  * byte 6 = 0x2: to identify it as locally administered SA MAC
   53  * byte 12 = 0x81 & byte 13 = 0x00:
   54  *      In case of VLAN filter first two bytes defines ether type (0x8100)
   55  *      and remaining two bytes are placeholder for programming a given VLAN ID
   56  *      In case of Ether type filter it is treated as header without VLAN tag
   57  *      and byte 12 and 13 is used to program a given Ether type instead
   58  */
   59 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
   60                                                         0x2, 0, 0, 0, 0, 0,
   61                                                         0x81, 0, 0, 0};
   62 
   63 /**
   64  * ice_init_def_sw_recp - initialize the recipe book keeping tables
   65  * @hw: pointer to the HW struct
   66  * @recp_list: pointer to sw recipe list
   67  *
   68  * Allocate memory for the entire recipe table and initialize the structures/
   69  * entries corresponding to basic recipes.
   70  */
   71 enum ice_status
   72 ice_init_def_sw_recp(struct ice_hw *hw, struct ice_sw_recipe **recp_list)
   73 {
   74         struct ice_sw_recipe *recps;
   75         u8 i;
   76 
   77         recps = (struct ice_sw_recipe *)
   78                 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps));
   79         if (!recps)
   80                 return ICE_ERR_NO_MEMORY;
   81 
   82         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
   83                 recps[i].root_rid = i;
   84                 INIT_LIST_HEAD(&recps[i].filt_rules);
   85                 INIT_LIST_HEAD(&recps[i].filt_replay_rules);
   86                 INIT_LIST_HEAD(&recps[i].rg_list);
   87                 ice_init_lock(&recps[i].filt_rule_lock);
   88         }
   89 
   90         *recp_list = recps;
   91 
   92         return ICE_SUCCESS;
   93 }
   94 
   95 /**
   96  * ice_aq_get_sw_cfg - get switch configuration
   97  * @hw: pointer to the hardware structure
   98  * @buf: pointer to the result buffer
   99  * @buf_size: length of the buffer available for response
  100  * @req_desc: pointer to requested descriptor
  101  * @num_elems: pointer to number of elements
  102  * @cd: pointer to command details structure or NULL
  103  *
  104  * Get switch configuration (0x0200) to be placed in buf.
  105  * This admin command returns information such as initial VSI/port number
  106  * and switch ID it belongs to.
  107  *
  108  * NOTE: *req_desc is both an input/output parameter.
  109  * The caller of this function first calls this function with *request_desc set
  110  * to 0. If the response from f/w has *req_desc set to 0, all the switch
  111  * configuration information has been returned; if non-zero (meaning not all
  112  * the information was returned), the caller should call this function again
  113  * with *req_desc set to the previous value returned by f/w to get the
  114  * next block of switch configuration information.
  115  *
  116  * *num_elems is output only parameter. This reflects the number of elements
  117  * in response buffer. The caller of this function to use *num_elems while
  118  * parsing the response buffer.
  119  */
  120 static enum ice_status
  121 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
  122                   u16 buf_size, u16 *req_desc, u16 *num_elems,
  123                   struct ice_sq_cd *cd)
  124 {
  125         struct ice_aqc_get_sw_cfg *cmd;
  126         struct ice_aq_desc desc;
  127         enum ice_status status;
  128 
  129         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
  130         cmd = &desc.params.get_sw_conf;
  131         cmd->element = CPU_TO_LE16(*req_desc);
  132 
  133         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
  134         if (!status) {
  135                 *req_desc = LE16_TO_CPU(cmd->element);
  136                 *num_elems = LE16_TO_CPU(cmd->num_elems);
  137         }
  138 
  139         return status;
  140 }
  141 
  142 /**
  143  * ice_alloc_rss_global_lut - allocate a RSS global LUT
  144  * @hw: pointer to the HW struct
  145  * @shared_res: true to allocate as a shared resource and false to allocate as a dedicated resource
  146  * @global_lut_id: output parameter for the RSS global LUT's ID
  147  */
  148 enum ice_status ice_alloc_rss_global_lut(struct ice_hw *hw, bool shared_res, u16 *global_lut_id)
  149 {
  150         struct ice_aqc_alloc_free_res_elem *sw_buf;
  151         enum ice_status status;
  152         u16 buf_len;
  153 
  154         buf_len = ice_struct_size(sw_buf, elem, 1);
  155         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
  156         if (!sw_buf)
  157                 return ICE_ERR_NO_MEMORY;
  158 
  159         sw_buf->num_elems = CPU_TO_LE16(1);
  160         sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH |
  161                                        (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
  162                                        ICE_AQC_RES_TYPE_FLAG_DEDICATED));
  163 
  164         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, ice_aqc_opc_alloc_res, NULL);
  165         if (status) {
  166                 ice_debug(hw, ICE_DBG_RES, "Failed to allocate %s RSS global LUT, status %d\n",
  167                           shared_res ? "shared" : "dedicated", status);
  168                 goto ice_alloc_global_lut_exit;
  169         }
  170 
  171         *global_lut_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
  172 
  173 ice_alloc_global_lut_exit:
  174         ice_free(hw, sw_buf);
  175         return status;
  176 }
  177 
  178 /**
  179  * ice_free_rss_global_lut - free a RSS global LUT
  180  * @hw: pointer to the HW struct
  181  * @global_lut_id: ID of the RSS global LUT to free
  182  */
  183 enum ice_status ice_free_rss_global_lut(struct ice_hw *hw, u16 global_lut_id)
  184 {
  185         struct ice_aqc_alloc_free_res_elem *sw_buf;
  186         u16 buf_len, num_elems = 1;
  187         enum ice_status status;
  188 
  189         buf_len = ice_struct_size(sw_buf, elem, num_elems);
  190         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
  191         if (!sw_buf)
  192                 return ICE_ERR_NO_MEMORY;
  193 
  194         sw_buf->num_elems = CPU_TO_LE16(num_elems);
  195         sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH);
  196         sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(global_lut_id);
  197 
  198         status = ice_aq_alloc_free_res(hw, num_elems, sw_buf, buf_len, ice_aqc_opc_free_res, NULL);
  199         if (status)
  200                 ice_debug(hw, ICE_DBG_RES, "Failed to free RSS global LUT %d, status %d\n",
  201                           global_lut_id, status);
  202 
  203         ice_free(hw, sw_buf);
  204         return status;
  205 }
  206 
  207 /**
  208  * ice_alloc_sw - allocate resources specific to switch
  209  * @hw: pointer to the HW struct
  210  * @ena_stats: true to turn on VEB stats
  211  * @shared_res: true for shared resource, false for dedicated resource
  212  * @sw_id: switch ID returned
  213  * @counter_id: VEB counter ID returned
  214  *
  215  * allocates switch resources (SWID and VEB counter) (0x0208)
  216  */
  217 enum ice_status
  218 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id,
  219              u16 *counter_id)
  220 {
  221         struct ice_aqc_alloc_free_res_elem *sw_buf;
  222         struct ice_aqc_res_elem *sw_ele;
  223         enum ice_status status;
  224         u16 buf_len;
  225 
  226         buf_len = ice_struct_size(sw_buf, elem, 1);
  227         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
  228         if (!sw_buf)
  229                 return ICE_ERR_NO_MEMORY;
  230 
  231         /* Prepare buffer for switch ID.
  232          * The number of resource entries in buffer is passed as 1 since only a
  233          * single switch/VEB instance is allocated, and hence a single sw_id
  234          * is requested.
  235          */
  236         sw_buf->num_elems = CPU_TO_LE16(1);
  237         sw_buf->res_type =
  238                 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID |
  239                             (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
  240                             ICE_AQC_RES_TYPE_FLAG_DEDICATED));
  241 
  242         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
  243                                        ice_aqc_opc_alloc_res, NULL);
  244 
  245         if (status)
  246                 goto ice_alloc_sw_exit;
  247 
  248         sw_ele = &sw_buf->elem[0];
  249         *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp);
  250 
  251         if (ena_stats) {
  252                 /* Prepare buffer for VEB Counter */
  253                 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res;
  254                 struct ice_aqc_alloc_free_res_elem *counter_buf;
  255                 struct ice_aqc_res_elem *counter_ele;
  256 
  257                 counter_buf = (struct ice_aqc_alloc_free_res_elem *)
  258                                 ice_malloc(hw, buf_len);
  259                 if (!counter_buf) {
  260                         status = ICE_ERR_NO_MEMORY;
  261                         goto ice_alloc_sw_exit;
  262                 }
  263 
  264                 /* The number of resource entries in buffer is passed as 1 since
  265                  * only a single switch/VEB instance is allocated, and hence a
  266                  * single VEB counter is requested.
  267                  */
  268                 counter_buf->num_elems = CPU_TO_LE16(1);
  269                 counter_buf->res_type =
  270                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER |
  271                                     ICE_AQC_RES_TYPE_FLAG_DEDICATED);
  272                 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
  273                                                opc, NULL);
  274 
  275                 if (status) {
  276                         ice_free(hw, counter_buf);
  277                         goto ice_alloc_sw_exit;
  278                 }
  279                 counter_ele = &counter_buf->elem[0];
  280                 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp);
  281                 ice_free(hw, counter_buf);
  282         }
  283 
  284 ice_alloc_sw_exit:
  285         ice_free(hw, sw_buf);
  286         return status;
  287 }
  288 
  289 /**
  290  * ice_free_sw - free resources specific to switch
  291  * @hw: pointer to the HW struct
  292  * @sw_id: switch ID returned
  293  * @counter_id: VEB counter ID returned
  294  *
  295  * free switch resources (SWID and VEB counter) (0x0209)
  296  *
  297  * NOTE: This function frees multiple resources. It continues
  298  * releasing other resources even after it encounters error.
  299  * The error code returned is the last error it encountered.
  300  */
  301 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id)
  302 {
  303         struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf;
  304         enum ice_status status, ret_status;
  305         u16 buf_len;
  306 
  307         buf_len = ice_struct_size(sw_buf, elem, 1);
  308         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
  309         if (!sw_buf)
  310                 return ICE_ERR_NO_MEMORY;
  311 
  312         /* Prepare buffer to free for switch ID res.
  313          * The number of resource entries in buffer is passed as 1 since only a
  314          * single switch/VEB instance is freed, and hence a single sw_id
  315          * is released.
  316          */
  317         sw_buf->num_elems = CPU_TO_LE16(1);
  318         sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID);
  319         sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id);
  320 
  321         ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
  322                                            ice_aqc_opc_free_res, NULL);
  323 
  324         if (ret_status)
  325                 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
  326 
  327         /* Prepare buffer to free for VEB Counter resource */
  328         counter_buf = (struct ice_aqc_alloc_free_res_elem *)
  329                         ice_malloc(hw, buf_len);
  330         if (!counter_buf) {
  331                 ice_free(hw, sw_buf);
  332                 return ICE_ERR_NO_MEMORY;
  333         }
  334 
  335         /* The number of resource entries in buffer is passed as 1 since only a
  336          * single switch/VEB instance is freed, and hence a single VEB counter
  337          * is released
  338          */
  339         counter_buf->num_elems = CPU_TO_LE16(1);
  340         counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER);
  341         counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
  342 
  343         status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
  344                                        ice_aqc_opc_free_res, NULL);
  345         if (status) {
  346                 ice_debug(hw, ICE_DBG_SW, "VEB counter resource could not be freed\n");
  347                 ret_status = status;
  348         }
  349 
  350         ice_free(hw, counter_buf);
  351         ice_free(hw, sw_buf);
  352         return ret_status;
  353 }
  354 
  355 /**
  356  * ice_aq_add_vsi
  357  * @hw: pointer to the HW struct
  358  * @vsi_ctx: pointer to a VSI context struct
  359  * @cd: pointer to command details structure or NULL
  360  *
  361  * Add a VSI context to the hardware (0x0210)
  362  */
  363 enum ice_status
  364 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
  365                struct ice_sq_cd *cd)
  366 {
  367         struct ice_aqc_add_update_free_vsi_resp *res;
  368         struct ice_aqc_add_get_update_free_vsi *cmd;
  369         struct ice_aq_desc desc;
  370         enum ice_status status;
  371 
  372         cmd = &desc.params.vsi_cmd;
  373         res = &desc.params.add_update_free_vsi_res;
  374 
  375         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
  376 
  377         if (!vsi_ctx->alloc_from_pool)
  378                 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num |
  379                                            ICE_AQ_VSI_IS_VALID);
  380         cmd->vf_id = vsi_ctx->vf_num;
  381 
  382         cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags);
  383 
  384         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
  385 
  386         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
  387                                  sizeof(vsi_ctx->info), cd);
  388 
  389         if (!status) {
  390                 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M;
  391                 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used);
  392                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free);
  393         }
  394 
  395         return status;
  396 }
  397 
  398 /**
  399  * ice_aq_free_vsi
  400  * @hw: pointer to the HW struct
  401  * @vsi_ctx: pointer to a VSI context struct
  402  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
  403  * @cd: pointer to command details structure or NULL
  404  *
  405  * Free VSI context info from hardware (0x0213)
  406  */
  407 enum ice_status
  408 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
  409                 bool keep_vsi_alloc, struct ice_sq_cd *cd)
  410 {
  411         struct ice_aqc_add_update_free_vsi_resp *resp;
  412         struct ice_aqc_add_get_update_free_vsi *cmd;
  413         struct ice_aq_desc desc;
  414         enum ice_status status;
  415 
  416         cmd = &desc.params.vsi_cmd;
  417         resp = &desc.params.add_update_free_vsi_res;
  418 
  419         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
  420 
  421         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
  422         if (keep_vsi_alloc)
  423                 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC);
  424 
  425         status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
  426         if (!status) {
  427                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
  428                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
  429         }
  430 
  431         return status;
  432 }
  433 
  434 /**
  435  * ice_aq_update_vsi
  436  * @hw: pointer to the HW struct
  437  * @vsi_ctx: pointer to a VSI context struct
  438  * @cd: pointer to command details structure or NULL
  439  *
  440  * Update VSI context in the hardware (0x0211)
  441  */
  442 enum ice_status
  443 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
  444                   struct ice_sq_cd *cd)
  445 {
  446         struct ice_aqc_add_update_free_vsi_resp *resp;
  447         struct ice_aqc_add_get_update_free_vsi *cmd;
  448         struct ice_aq_desc desc;
  449         enum ice_status status;
  450 
  451         cmd = &desc.params.vsi_cmd;
  452         resp = &desc.params.add_update_free_vsi_res;
  453 
  454         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
  455 
  456         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
  457 
  458         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
  459 
  460         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
  461                                  sizeof(vsi_ctx->info), cd);
  462 
  463         if (!status) {
  464                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
  465                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
  466         }
  467 
  468         return status;
  469 }
  470 
  471 /**
  472  * ice_is_vsi_valid - check whether the VSI is valid or not
  473  * @hw: pointer to the HW struct
  474  * @vsi_handle: VSI handle
  475  *
  476  * check whether the VSI is valid or not
  477  */
  478 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
  479 {
  480         return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
  481 }
  482 
  483 /**
  484  * ice_get_hw_vsi_num - return the HW VSI number
  485  * @hw: pointer to the HW struct
  486  * @vsi_handle: VSI handle
  487  *
  488  * return the HW VSI number
  489  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
  490  */
  491 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
  492 {
  493         return hw->vsi_ctx[vsi_handle]->vsi_num;
  494 }
  495 
  496 /**
  497  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
  498  * @hw: pointer to the HW struct
  499  * @vsi_handle: VSI handle
  500  *
  501  * return the VSI context entry for a given VSI handle
  502  */
  503 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
  504 {
  505         return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
  506 }
  507 
  508 /**
  509  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
  510  * @hw: pointer to the HW struct
  511  * @vsi_handle: VSI handle
  512  * @vsi: VSI context pointer
  513  *
  514  * save the VSI context entry for a given VSI handle
  515  */
  516 static void
  517 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
  518 {
  519         hw->vsi_ctx[vsi_handle] = vsi;
  520 }
  521 
  522 /**
  523  * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
  524  * @hw: pointer to the HW struct
  525  * @vsi_handle: VSI handle
  526  */
  527 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
  528 {
  529         struct ice_vsi_ctx *vsi;
  530         u8 i;
  531 
  532         vsi = ice_get_vsi_ctx(hw, vsi_handle);
  533         if (!vsi)
  534                 return;
  535         ice_for_each_traffic_class(i) {
  536                 if (vsi->lan_q_ctx[i]) {
  537                         ice_free(hw, vsi->lan_q_ctx[i]);
  538                         vsi->lan_q_ctx[i] = NULL;
  539                 }
  540                 if (vsi->rdma_q_ctx[i]) {
  541                         ice_free(hw, vsi->rdma_q_ctx[i]);
  542                         vsi->rdma_q_ctx[i] = NULL;
  543                 }
  544         }
  545 }
  546 
  547 /**
  548  * ice_clear_vsi_ctx - clear the VSI context entry
  549  * @hw: pointer to the HW struct
  550  * @vsi_handle: VSI handle
  551  *
  552  * clear the VSI context entry
  553  */
  554 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
  555 {
  556         struct ice_vsi_ctx *vsi;
  557 
  558         vsi = ice_get_vsi_ctx(hw, vsi_handle);
  559         if (vsi) {
  560                 ice_clear_vsi_q_ctx(hw, vsi_handle);
  561                 ice_free(hw, vsi);
  562                 hw->vsi_ctx[vsi_handle] = NULL;
  563         }
  564 }
  565 
  566 /**
  567  * ice_clear_all_vsi_ctx - clear all the VSI context entries
  568  * @hw: pointer to the HW struct
  569  */
  570 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
  571 {
  572         u16 i;
  573 
  574         for (i = 0; i < ICE_MAX_VSI; i++)
  575                 ice_clear_vsi_ctx(hw, i);
  576 }
  577 
  578 /**
  579  * ice_add_vsi - add VSI context to the hardware and VSI handle list
  580  * @hw: pointer to the HW struct
  581  * @vsi_handle: unique VSI handle provided by drivers
  582  * @vsi_ctx: pointer to a VSI context struct
  583  * @cd: pointer to command details structure or NULL
  584  *
  585  * Add a VSI context to the hardware also add it into the VSI handle list.
  586  * If this function gets called after reset for existing VSIs then update
  587  * with the new HW VSI number in the corresponding VSI handle list entry.
  588  */
  589 enum ice_status
  590 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
  591             struct ice_sq_cd *cd)
  592 {
  593         struct ice_vsi_ctx *tmp_vsi_ctx;
  594         enum ice_status status;
  595 
  596         if (vsi_handle >= ICE_MAX_VSI)
  597                 return ICE_ERR_PARAM;
  598         status = ice_aq_add_vsi(hw, vsi_ctx, cd);
  599         if (status)
  600                 return status;
  601         tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
  602         if (!tmp_vsi_ctx) {
  603                 /* Create a new VSI context */
  604                 tmp_vsi_ctx = (struct ice_vsi_ctx *)
  605                         ice_malloc(hw, sizeof(*tmp_vsi_ctx));
  606                 if (!tmp_vsi_ctx) {
  607                         ice_aq_free_vsi(hw, vsi_ctx, false, cd);
  608                         return ICE_ERR_NO_MEMORY;
  609                 }
  610                 *tmp_vsi_ctx = *vsi_ctx;
  611 
  612                 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
  613         } else {
  614                 /* update with new HW VSI num */
  615                 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
  616         }
  617 
  618         return ICE_SUCCESS;
  619 }
  620 
  621 /**
  622  * ice_free_vsi- free VSI context from hardware and VSI handle list
  623  * @hw: pointer to the HW struct
  624  * @vsi_handle: unique VSI handle
  625  * @vsi_ctx: pointer to a VSI context struct
  626  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
  627  * @cd: pointer to command details structure or NULL
  628  *
  629  * Free VSI context info from hardware as well as from VSI handle list
  630  */
  631 enum ice_status
  632 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
  633              bool keep_vsi_alloc, struct ice_sq_cd *cd)
  634 {
  635         enum ice_status status;
  636 
  637         if (!ice_is_vsi_valid(hw, vsi_handle))
  638                 return ICE_ERR_PARAM;
  639         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
  640         status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
  641         if (!status)
  642                 ice_clear_vsi_ctx(hw, vsi_handle);
  643         return status;
  644 }
  645 
  646 /**
  647  * ice_update_vsi
  648  * @hw: pointer to the HW struct
  649  * @vsi_handle: unique VSI handle
  650  * @vsi_ctx: pointer to a VSI context struct
  651  * @cd: pointer to command details structure or NULL
  652  *
  653  * Update VSI context in the hardware
  654  */
  655 enum ice_status
  656 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
  657                struct ice_sq_cd *cd)
  658 {
  659         if (!ice_is_vsi_valid(hw, vsi_handle))
  660                 return ICE_ERR_PARAM;
  661         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
  662         return ice_aq_update_vsi(hw, vsi_ctx, cd);
  663 }
  664 
  665 /**
  666  * ice_cfg_iwarp_fltr - enable/disable iWARP filtering on VSI
  667  * @hw: pointer to HW struct
  668  * @vsi_handle: VSI SW index
  669  * @enable: boolean for enable/disable
  670  */
  671 enum ice_status
  672 ice_cfg_iwarp_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
  673 {
  674         struct ice_vsi_ctx *ctx, *cached_ctx;
  675         enum ice_status status;
  676 
  677         cached_ctx = ice_get_vsi_ctx(hw, vsi_handle);
  678         if (!cached_ctx)
  679                 return ICE_ERR_DOES_NOT_EXIST;
  680 
  681         ctx = (struct ice_vsi_ctx *)ice_calloc(hw, 1, sizeof(*ctx));
  682         if (!ctx)
  683                 return ICE_ERR_NO_MEMORY;
  684 
  685         ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss;
  686         ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc;
  687         ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags;
  688 
  689         ctx->info.valid_sections = CPU_TO_LE16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
  690 
  691         if (enable)
  692                 ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
  693         else
  694                 ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
  695 
  696         status = ice_update_vsi(hw, vsi_handle, ctx, NULL);
  697         if (!status) {
  698                 cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags;
  699                 cached_ctx->info.valid_sections |= ctx->info.valid_sections;
  700         }
  701 
  702         ice_free(hw, ctx);
  703         return status;
  704 }
  705 
  706 /**
  707  * ice_aq_get_vsi_params
  708  * @hw: pointer to the HW struct
  709  * @vsi_ctx: pointer to a VSI context struct
  710  * @cd: pointer to command details structure or NULL
  711  *
  712  * Get VSI context info from hardware (0x0212)
  713  */
  714 enum ice_status
  715 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
  716                       struct ice_sq_cd *cd)
  717 {
  718         struct ice_aqc_add_get_update_free_vsi *cmd;
  719         struct ice_aqc_get_vsi_resp *resp;
  720         struct ice_aq_desc desc;
  721         enum ice_status status;
  722 
  723         cmd = &desc.params.vsi_cmd;
  724         resp = &desc.params.get_vsi_resp;
  725 
  726         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params);
  727 
  728         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
  729 
  730         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
  731                                  sizeof(vsi_ctx->info), cd);
  732         if (!status) {
  733                 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) &
  734                                         ICE_AQ_VSI_NUM_M;
  735                 vsi_ctx->vf_num = resp->vf_id;
  736                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
  737                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
  738         }
  739 
  740         return status;
  741 }
  742 
  743 /**
  744  * ice_aq_add_update_mir_rule - add/update a mirror rule
  745  * @hw: pointer to the HW struct
  746  * @rule_type: Rule Type
  747  * @dest_vsi: VSI number to which packets will be mirrored
  748  * @count: length of the list
  749  * @mr_buf: buffer for list of mirrored VSI numbers
  750  * @cd: pointer to command details structure or NULL
  751  * @rule_id: Rule ID
  752  *
  753  * Add/Update Mirror Rule (0x260).
  754  */
  755 enum ice_status
  756 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi,
  757                            u16 count, struct ice_mir_rule_buf *mr_buf,
  758                            struct ice_sq_cd *cd, u16 *rule_id)
  759 {
  760         struct ice_aqc_add_update_mir_rule *cmd;
  761         struct ice_aq_desc desc;
  762         enum ice_status status;
  763         __le16 *mr_list = NULL;
  764         u16 buf_size = 0;
  765 
  766         switch (rule_type) {
  767         case ICE_AQC_RULE_TYPE_VPORT_INGRESS:
  768         case ICE_AQC_RULE_TYPE_VPORT_EGRESS:
  769                 /* Make sure count and mr_buf are set for these rule_types */
  770                 if (!(count && mr_buf))
  771                         return ICE_ERR_PARAM;
  772 
  773                 buf_size = count * sizeof(__le16);
  774                 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size);
  775                 if (!mr_list)
  776                         return ICE_ERR_NO_MEMORY;
  777                 break;
  778         case ICE_AQC_RULE_TYPE_PPORT_INGRESS:
  779         case ICE_AQC_RULE_TYPE_PPORT_EGRESS:
  780                 /* Make sure count and mr_buf are not set for these
  781                  * rule_types
  782                  */
  783                 if (count || mr_buf)
  784                         return ICE_ERR_PARAM;
  785                 break;
  786         default:
  787                 ice_debug(hw, ICE_DBG_SW, "Error due to unsupported rule_type %u\n", rule_type);
  788                 return ICE_ERR_OUT_OF_RANGE;
  789         }
  790 
  791         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule);
  792 
  793         /* Pre-process 'mr_buf' items for add/update of virtual port
  794          * ingress/egress mirroring (but not physical port ingress/egress
  795          * mirroring)
  796          */
  797         if (mr_buf) {
  798                 int i;
  799 
  800                 for (i = 0; i < count; i++) {
  801                         u16 id;
  802 
  803                         id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M;
  804 
  805                         /* Validate specified VSI number, make sure it is less
  806                          * than ICE_MAX_VSI, if not return with error.
  807                          */
  808                         if (id >= ICE_MAX_VSI) {
  809                                 ice_debug(hw, ICE_DBG_SW, "Error VSI index (%u) out-of-range\n",
  810                                           id);
  811                                 ice_free(hw, mr_list);
  812                                 return ICE_ERR_OUT_OF_RANGE;
  813                         }
  814 
  815                         /* add VSI to mirror rule */
  816                         if (mr_buf[i].add)
  817                                 mr_list[i] =
  818                                         CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M);
  819                         else /* remove VSI from mirror rule */
  820                                 mr_list[i] = CPU_TO_LE16(id);
  821                 }
  822         }
  823 
  824         cmd = &desc.params.add_update_rule;
  825         if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID)
  826                 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) |
  827                                            ICE_AQC_RULE_ID_VALID_M);
  828         cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M);
  829         cmd->num_entries = CPU_TO_LE16(count);
  830         cmd->dest = CPU_TO_LE16(dest_vsi);
  831 
  832         status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd);
  833         if (!status)
  834                 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M;
  835 
  836         ice_free(hw, mr_list);
  837 
  838         return status;
  839 }
  840 
  841 /**
  842  * ice_aq_delete_mir_rule - delete a mirror rule
  843  * @hw: pointer to the HW struct
  844  * @rule_id: Mirror rule ID (to be deleted)
  845  * @keep_allocd: if set, the VSI stays part of the PF allocated res,
  846  *               otherwise it is returned to the shared pool
  847  * @cd: pointer to command details structure or NULL
  848  *
  849  * Delete Mirror Rule (0x261).
  850  */
  851 enum ice_status
  852 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd,
  853                        struct ice_sq_cd *cd)
  854 {
  855         struct ice_aqc_delete_mir_rule *cmd;
  856         struct ice_aq_desc desc;
  857 
  858         /* rule_id should be in the range 0...63 */
  859         if (rule_id >= ICE_MAX_NUM_MIRROR_RULES)
  860                 return ICE_ERR_OUT_OF_RANGE;
  861 
  862         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule);
  863 
  864         cmd = &desc.params.del_rule;
  865         rule_id |= ICE_AQC_RULE_ID_VALID_M;
  866         cmd->rule_id = CPU_TO_LE16(rule_id);
  867 
  868         if (keep_allocd)
  869                 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M);
  870 
  871         return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
  872 }
  873 
  874 /**
  875  * ice_aq_alloc_free_vsi_list
  876  * @hw: pointer to the HW struct
  877  * @vsi_list_id: VSI list ID returned or used for lookup
  878  * @lkup_type: switch rule filter lookup type
  879  * @opc: switch rules population command type - pass in the command opcode
  880  *
  881  * allocates or free a VSI list resource
  882  */
  883 static enum ice_status
  884 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
  885                            enum ice_sw_lkup_type lkup_type,
  886                            enum ice_adminq_opc opc)
  887 {
  888         struct ice_aqc_alloc_free_res_elem *sw_buf;
  889         struct ice_aqc_res_elem *vsi_ele;
  890         enum ice_status status;
  891         u16 buf_len;
  892 
  893         buf_len = ice_struct_size(sw_buf, elem, 1);
  894         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
  895         if (!sw_buf)
  896                 return ICE_ERR_NO_MEMORY;
  897         sw_buf->num_elems = CPU_TO_LE16(1);
  898 
  899         if (lkup_type == ICE_SW_LKUP_MAC ||
  900             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
  901             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
  902             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
  903             lkup_type == ICE_SW_LKUP_PROMISC ||
  904             lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
  905             lkup_type == ICE_SW_LKUP_LAST) {
  906                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
  907         } else if (lkup_type == ICE_SW_LKUP_VLAN) {
  908                 sw_buf->res_type =
  909                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
  910         } else {
  911                 status = ICE_ERR_PARAM;
  912                 goto ice_aq_alloc_free_vsi_list_exit;
  913         }
  914 
  915         if (opc == ice_aqc_opc_free_res)
  916                 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id);
  917 
  918         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
  919         if (status)
  920                 goto ice_aq_alloc_free_vsi_list_exit;
  921 
  922         if (opc == ice_aqc_opc_alloc_res) {
  923                 vsi_ele = &sw_buf->elem[0];
  924                 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp);
  925         }
  926 
  927 ice_aq_alloc_free_vsi_list_exit:
  928         ice_free(hw, sw_buf);
  929         return status;
  930 }
  931 
  932 /**
  933  * ice_aq_set_storm_ctrl - Sets storm control configuration
  934  * @hw: pointer to the HW struct
  935  * @bcast_thresh: represents the upper threshold for broadcast storm control
  936  * @mcast_thresh: represents the upper threshold for multicast storm control
  937  * @ctl_bitmask: storm control knobs
  938  *
  939  * Sets the storm control configuration (0x0280)
  940  */
  941 enum ice_status
  942 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh,
  943                       u32 ctl_bitmask)
  944 {
  945         struct ice_aqc_storm_cfg *cmd;
  946         struct ice_aq_desc desc;
  947 
  948         cmd = &desc.params.storm_conf;
  949 
  950         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg);
  951 
  952         cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M);
  953         cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M);
  954         cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask);
  955 
  956         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
  957 }
  958 
  959 /**
  960  * ice_aq_get_storm_ctrl - gets storm control configuration
  961  * @hw: pointer to the HW struct
  962  * @bcast_thresh: represents the upper threshold for broadcast storm control
  963  * @mcast_thresh: represents the upper threshold for multicast storm control
  964  * @ctl_bitmask: storm control knobs
  965  *
  966  * Gets the storm control configuration (0x0281)
  967  */
  968 enum ice_status
  969 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh,
  970                       u32 *ctl_bitmask)
  971 {
  972         enum ice_status status;
  973         struct ice_aq_desc desc;
  974 
  975         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg);
  976 
  977         status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
  978         if (!status) {
  979                 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf;
  980 
  981                 if (bcast_thresh)
  982                         *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) &
  983                                 ICE_AQ_THRESHOLD_M;
  984                 if (mcast_thresh)
  985                         *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) &
  986                                 ICE_AQ_THRESHOLD_M;
  987                 if (ctl_bitmask)
  988                         *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl);
  989         }
  990 
  991         return status;
  992 }
  993 
  994 /**
  995  * ice_aq_sw_rules - add/update/remove switch rules
  996  * @hw: pointer to the HW struct
  997  * @rule_list: pointer to switch rule population list
  998  * @rule_list_sz: total size of the rule list in bytes
  999  * @num_rules: number of switch rules in the rule_list
 1000  * @opc: switch rules population command type - pass in the command opcode
 1001  * @cd: pointer to command details structure or NULL
 1002  *
 1003  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
 1004  */
 1005 static enum ice_status
 1006 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
 1007                 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
 1008 {
 1009         struct ice_aq_desc desc;
 1010         enum ice_status status;
 1011 
 1012         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 1013 
 1014         if (opc != ice_aqc_opc_add_sw_rules &&
 1015             opc != ice_aqc_opc_update_sw_rules &&
 1016             opc != ice_aqc_opc_remove_sw_rules)
 1017                 return ICE_ERR_PARAM;
 1018 
 1019         ice_fill_dflt_direct_cmd_desc(&desc, opc);
 1020 
 1021         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
 1022         desc.params.sw_rules.num_rules_fltr_entry_index =
 1023                 CPU_TO_LE16(num_rules);
 1024         status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
 1025         if (opc != ice_aqc_opc_add_sw_rules &&
 1026             hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
 1027                 status = ICE_ERR_DOES_NOT_EXIST;
 1028 
 1029         return status;
 1030 }
 1031 
 1032 /* ice_init_port_info - Initialize port_info with switch configuration data
 1033  * @pi: pointer to port_info
 1034  * @vsi_port_num: VSI number or port number
 1035  * @type: Type of switch element (port or VSI)
 1036  * @swid: switch ID of the switch the element is attached to
 1037  * @pf_vf_num: PF or VF number
 1038  * @is_vf: true if the element is a VF, false otherwise
 1039  */
 1040 static void
 1041 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
 1042                    u16 swid, u16 pf_vf_num, bool is_vf)
 1043 {
 1044         switch (type) {
 1045         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
 1046                 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
 1047                 pi->sw_id = swid;
 1048                 pi->pf_vf_num = pf_vf_num;
 1049                 pi->is_vf = is_vf;
 1050                 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
 1051                 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
 1052                 break;
 1053         default:
 1054                 ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
 1055                 break;
 1056         }
 1057 }
 1058 
 1059 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
 1060  * @hw: pointer to the hardware structure
 1061  */
 1062 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
 1063 {
 1064         struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
 1065         enum ice_status status;
 1066         u8 num_total_ports;
 1067         u16 req_desc = 0;
 1068         u16 num_elems;
 1069         u8 j = 0;
 1070         u16 i;
 1071 
 1072         num_total_ports = 1;
 1073 
 1074         rbuf = (struct ice_aqc_get_sw_cfg_resp_elem *)
 1075                 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN);
 1076 
 1077         if (!rbuf)
 1078                 return ICE_ERR_NO_MEMORY;
 1079 
 1080         /* Multiple calls to ice_aq_get_sw_cfg may be required
 1081          * to get all the switch configuration information. The need
 1082          * for additional calls is indicated by ice_aq_get_sw_cfg
 1083          * writing a non-zero value in req_desc
 1084          */
 1085         do {
 1086                 struct ice_aqc_get_sw_cfg_resp_elem *ele;
 1087 
 1088                 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
 1089                                            &req_desc, &num_elems, NULL);
 1090 
 1091                 if (status)
 1092                         break;
 1093 
 1094                 for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
 1095                         u16 pf_vf_num, swid, vsi_port_num;
 1096                         bool is_vf = false;
 1097                         u8 res_type;
 1098 
 1099                         vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) &
 1100                                 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
 1101 
 1102                         pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) &
 1103                                 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
 1104 
 1105                         swid = LE16_TO_CPU(ele->swid);
 1106 
 1107                         if (LE16_TO_CPU(ele->pf_vf_num) &
 1108                             ICE_AQC_GET_SW_CONF_RESP_IS_VF)
 1109                                 is_vf = true;
 1110 
 1111                         res_type = (u8)(LE16_TO_CPU(ele->vsi_port_num) >>
 1112                                         ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
 1113 
 1114                         switch (res_type) {
 1115                         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
 1116                         case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT:
 1117                                 if (j == num_total_ports) {
 1118                                         ice_debug(hw, ICE_DBG_SW, "more ports than expected\n");
 1119                                         status = ICE_ERR_CFG;
 1120                                         goto out;
 1121                                 }
 1122                                 ice_init_port_info(hw->port_info,
 1123                                                    vsi_port_num, res_type, swid,
 1124                                                    pf_vf_num, is_vf);
 1125                                 j++;
 1126                                 break;
 1127                         default:
 1128                                 break;
 1129                         }
 1130                 }
 1131         } while (req_desc && !status);
 1132 
 1133 out:
 1134         ice_free(hw, rbuf);
 1135         return status;
 1136 }
 1137 
 1138 /**
 1139  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
 1140  * @hw: pointer to the hardware structure
 1141  * @fi: filter info structure to fill/update
 1142  *
 1143  * This helper function populates the lb_en and lan_en elements of the provided
 1144  * ice_fltr_info struct using the switch's type and characteristics of the
 1145  * switch rule being configured.
 1146  */
 1147 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
 1148 {
 1149         fi->lb_en = false;
 1150         fi->lan_en = false;
 1151         if ((fi->flag & ICE_FLTR_TX) &&
 1152             (fi->fltr_act == ICE_FWD_TO_VSI ||
 1153              fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
 1154              fi->fltr_act == ICE_FWD_TO_Q ||
 1155              fi->fltr_act == ICE_FWD_TO_QGRP)) {
 1156                 /* Setting LB for prune actions will result in replicated
 1157                  * packets to the internal switch that will be dropped.
 1158                  */
 1159                 if (fi->lkup_type != ICE_SW_LKUP_VLAN)
 1160                         fi->lb_en = true;
 1161 
 1162                 /* Set lan_en to TRUE if
 1163                  * 1. The switch is a VEB AND
 1164                  * 2
 1165                  * 2.1 The lookup is a directional lookup like ethertype,
 1166                  * promiscuous, ethertype-MAC, promiscuous-VLAN
 1167                  * and default-port OR
 1168                  * 2.2 The lookup is VLAN, OR
 1169                  * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
 1170                  * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
 1171                  *
 1172                  * OR
 1173                  *
 1174                  * The switch is a VEPA.
 1175                  *
 1176                  * In all other cases, the LAN enable has to be set to false.
 1177                  */
 1178                 if (hw->evb_veb) {
 1179                         if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
 1180                             fi->lkup_type == ICE_SW_LKUP_PROMISC ||
 1181                             fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
 1182                             fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
 1183                             fi->lkup_type == ICE_SW_LKUP_DFLT ||
 1184                             fi->lkup_type == ICE_SW_LKUP_VLAN ||
 1185                             (fi->lkup_type == ICE_SW_LKUP_MAC &&
 1186                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) ||
 1187                             (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
 1188                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)))
 1189                                 fi->lan_en = true;
 1190                 } else {
 1191                         fi->lan_en = true;
 1192                 }
 1193         }
 1194 }
 1195 
 1196 /**
 1197  * ice_fill_sw_rule - Helper function to fill switch rule structure
 1198  * @hw: pointer to the hardware structure
 1199  * @f_info: entry containing packet forwarding information
 1200  * @s_rule: switch rule structure to be filled in based on mac_entry
 1201  * @opc: switch rules population command type - pass in the command opcode
 1202  */
 1203 static void
 1204 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
 1205                  struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
 1206 {
 1207         u16 vlan_id = ICE_MAX_VLAN_ID + 1;
 1208         u16 vlan_tpid = ICE_ETH_P_8021Q;
 1209         void *daddr = NULL;
 1210         u16 eth_hdr_sz;
 1211         u8 *eth_hdr;
 1212         u32 act = 0;
 1213         __be16 *off;
 1214         u8 q_rgn;
 1215 
 1216         if (opc == ice_aqc_opc_remove_sw_rules) {
 1217                 s_rule->pdata.lkup_tx_rx.act = 0;
 1218                 s_rule->pdata.lkup_tx_rx.index =
 1219                         CPU_TO_LE16(f_info->fltr_rule_id);
 1220                 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
 1221                 return;
 1222         }
 1223 
 1224         eth_hdr_sz = sizeof(dummy_eth_header);
 1225         eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
 1226 
 1227         /* initialize the ether header with a dummy header */
 1228         ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA);
 1229         ice_fill_sw_info(hw, f_info);
 1230 
 1231         switch (f_info->fltr_act) {
 1232         case ICE_FWD_TO_VSI:
 1233                 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
 1234                         ICE_SINGLE_ACT_VSI_ID_M;
 1235                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
 1236                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
 1237                                 ICE_SINGLE_ACT_VALID_BIT;
 1238                 break;
 1239         case ICE_FWD_TO_VSI_LIST:
 1240                 act |= ICE_SINGLE_ACT_VSI_LIST;
 1241                 act |= (f_info->fwd_id.vsi_list_id <<
 1242                         ICE_SINGLE_ACT_VSI_LIST_ID_S) &
 1243                         ICE_SINGLE_ACT_VSI_LIST_ID_M;
 1244                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
 1245                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
 1246                                 ICE_SINGLE_ACT_VALID_BIT;
 1247                 break;
 1248         case ICE_FWD_TO_Q:
 1249                 act |= ICE_SINGLE_ACT_TO_Q;
 1250                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
 1251                         ICE_SINGLE_ACT_Q_INDEX_M;
 1252                 break;
 1253         case ICE_DROP_PACKET:
 1254                 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
 1255                         ICE_SINGLE_ACT_VALID_BIT;
 1256                 break;
 1257         case ICE_FWD_TO_QGRP:
 1258                 q_rgn = f_info->qgrp_size > 0 ?
 1259                         (u8)ice_ilog2(f_info->qgrp_size) : 0;
 1260                 act |= ICE_SINGLE_ACT_TO_Q;
 1261                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
 1262                         ICE_SINGLE_ACT_Q_INDEX_M;
 1263                 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
 1264                         ICE_SINGLE_ACT_Q_REGION_M;
 1265                 break;
 1266         default:
 1267                 return;
 1268         }
 1269 
 1270         if (f_info->lb_en)
 1271                 act |= ICE_SINGLE_ACT_LB_ENABLE;
 1272         if (f_info->lan_en)
 1273                 act |= ICE_SINGLE_ACT_LAN_ENABLE;
 1274 
 1275         switch (f_info->lkup_type) {
 1276         case ICE_SW_LKUP_MAC:
 1277                 daddr = f_info->l_data.mac.mac_addr;
 1278                 break;
 1279         case ICE_SW_LKUP_VLAN:
 1280                 vlan_id = f_info->l_data.vlan.vlan_id;
 1281                 if (f_info->l_data.vlan.tpid_valid)
 1282                         vlan_tpid = f_info->l_data.vlan.tpid;
 1283                 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
 1284                     f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
 1285                         act |= ICE_SINGLE_ACT_PRUNE;
 1286                         act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
 1287                 }
 1288                 break;
 1289         case ICE_SW_LKUP_ETHERTYPE_MAC:
 1290                 daddr = f_info->l_data.ethertype_mac.mac_addr;
 1291                 /* fall-through */
 1292         case ICE_SW_LKUP_ETHERTYPE:
 1293                 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
 1294                 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype);
 1295                 break;
 1296         case ICE_SW_LKUP_MAC_VLAN:
 1297                 daddr = f_info->l_data.mac_vlan.mac_addr;
 1298                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
 1299                 break;
 1300         case ICE_SW_LKUP_PROMISC_VLAN:
 1301                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
 1302                 /* fall-through */
 1303         case ICE_SW_LKUP_PROMISC:
 1304                 daddr = f_info->l_data.mac_vlan.mac_addr;
 1305                 break;
 1306         default:
 1307                 break;
 1308         }
 1309 
 1310         s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
 1311                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) :
 1312                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
 1313 
 1314         /* Recipe set depending on lookup type */
 1315         s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type);
 1316         s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src);
 1317         s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
 1318 
 1319         if (daddr)
 1320                 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN,
 1321                            ICE_NONDMA_TO_NONDMA);
 1322 
 1323         if (!(vlan_id > ICE_MAX_VLAN_ID)) {
 1324                 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
 1325                 *off = CPU_TO_BE16(vlan_id);
 1326                 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
 1327                 *off = CPU_TO_BE16(vlan_tpid);
 1328         }
 1329 
 1330         /* Create the switch rule with the final dummy Ethernet header */
 1331         if (opc != ice_aqc_opc_update_sw_rules)
 1332                 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz);
 1333 }
 1334 
 1335 /**
 1336  * ice_add_marker_act
 1337  * @hw: pointer to the hardware structure
 1338  * @m_ent: the management entry for which sw marker needs to be added
 1339  * @sw_marker: sw marker to tag the Rx descriptor with
 1340  * @l_id: large action resource ID
 1341  *
 1342  * Create a large action to hold software marker and update the switch rule
 1343  * entry pointed by m_ent with newly created large action
 1344  */
 1345 static enum ice_status
 1346 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
 1347                    u16 sw_marker, u16 l_id)
 1348 {
 1349         struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
 1350         /* For software marker we need 3 large actions
 1351          * 1. FWD action: FWD TO VSI or VSI LIST
 1352          * 2. GENERIC VALUE action to hold the profile ID
 1353          * 3. GENERIC VALUE action to hold the software marker ID
 1354          */
 1355         const u16 num_lg_acts = 3;
 1356         enum ice_status status;
 1357         u16 lg_act_size;
 1358         u16 rules_size;
 1359         u32 act;
 1360         u16 id;
 1361 
 1362         if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
 1363                 return ICE_ERR_PARAM;
 1364 
 1365         /* Create two back-to-back switch rules and submit them to the HW using
 1366          * one memory buffer:
 1367          *    1. Large Action
 1368          *    2. Look up Tx Rx
 1369          */
 1370         lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
 1371         rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
 1372         lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
 1373         if (!lg_act)
 1374                 return ICE_ERR_NO_MEMORY;
 1375 
 1376         rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
 1377 
 1378         /* Fill in the first switch rule i.e. large action */
 1379         lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
 1380         lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
 1381         lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts);
 1382 
 1383         /* First action VSI forwarding or VSI list forwarding depending on how
 1384          * many VSIs
 1385          */
 1386         id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
 1387                 m_ent->fltr_info.fwd_id.hw_vsi_id;
 1388 
 1389         act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
 1390         act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
 1391         if (m_ent->vsi_count > 1)
 1392                 act |= ICE_LG_ACT_VSI_LIST;
 1393         lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
 1394 
 1395         /* Second action descriptor type */
 1396         act = ICE_LG_ACT_GENERIC;
 1397 
 1398         act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
 1399         lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
 1400 
 1401         act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
 1402                ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
 1403 
 1404         /* Third action Marker value */
 1405         act |= ICE_LG_ACT_GENERIC;
 1406         act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
 1407                 ICE_LG_ACT_GENERIC_VALUE_M;
 1408 
 1409         lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act);
 1410 
 1411         /* call the fill switch rule to fill the lookup Tx Rx structure */
 1412         ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
 1413                          ice_aqc_opc_update_sw_rules);
 1414 
 1415         /* Update the action to point to the large action ID */
 1416         rx_tx->pdata.lkup_tx_rx.act =
 1417                 CPU_TO_LE32(ICE_SINGLE_ACT_PTR |
 1418                             ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
 1419                              ICE_SINGLE_ACT_PTR_VAL_M));
 1420 
 1421         /* Use the filter rule ID of the previously created rule with single
 1422          * act. Once the update happens, hardware will treat this as large
 1423          * action
 1424          */
 1425         rx_tx->pdata.lkup_tx_rx.index =
 1426                 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id);
 1427 
 1428         status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
 1429                                  ice_aqc_opc_update_sw_rules, NULL);
 1430         if (!status) {
 1431                 m_ent->lg_act_idx = l_id;
 1432                 m_ent->sw_marker_id = sw_marker;
 1433         }
 1434 
 1435         ice_free(hw, lg_act);
 1436         return status;
 1437 }
 1438 
 1439 /**
 1440  * ice_add_counter_act - add/update filter rule with counter action
 1441  * @hw: pointer to the hardware structure
 1442  * @m_ent: the management entry for which counter needs to be added
 1443  * @counter_id: VLAN counter ID returned as part of allocate resource
 1444  * @l_id: large action resource ID
 1445  */
 1446 static enum ice_status
 1447 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
 1448                     u16 counter_id, u16 l_id)
 1449 {
 1450         struct ice_aqc_sw_rules_elem *lg_act;
 1451         struct ice_aqc_sw_rules_elem *rx_tx;
 1452         enum ice_status status;
 1453         /* 2 actions will be added while adding a large action counter */
 1454         const int num_acts = 2;
 1455         u16 lg_act_size;
 1456         u16 rules_size;
 1457         u16 f_rule_id;
 1458         u32 act;
 1459         u16 id;
 1460 
 1461         if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
 1462                 return ICE_ERR_PARAM;
 1463 
 1464         /* Create two back-to-back switch rules and submit them to the HW using
 1465          * one memory buffer:
 1466          * 1. Large Action
 1467          * 2. Look up Tx Rx
 1468          */
 1469         lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts);
 1470         rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
 1471         lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
 1472         if (!lg_act)
 1473                 return ICE_ERR_NO_MEMORY;
 1474 
 1475         rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
 1476 
 1477         /* Fill in the first switch rule i.e. large action */
 1478         lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
 1479         lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
 1480         lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts);
 1481 
 1482         /* First action VSI forwarding or VSI list forwarding depending on how
 1483          * many VSIs
 1484          */
 1485         id = (m_ent->vsi_count > 1) ?  m_ent->fltr_info.fwd_id.vsi_list_id :
 1486                 m_ent->fltr_info.fwd_id.hw_vsi_id;
 1487 
 1488         act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
 1489         act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
 1490                 ICE_LG_ACT_VSI_LIST_ID_M;
 1491         if (m_ent->vsi_count > 1)
 1492                 act |= ICE_LG_ACT_VSI_LIST;
 1493         lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
 1494 
 1495         /* Second action counter ID */
 1496         act = ICE_LG_ACT_STAT_COUNT;
 1497         act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) &
 1498                 ICE_LG_ACT_STAT_COUNT_M;
 1499         lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
 1500 
 1501         /* call the fill switch rule to fill the lookup Tx Rx structure */
 1502         ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
 1503                          ice_aqc_opc_update_sw_rules);
 1504 
 1505         act = ICE_SINGLE_ACT_PTR;
 1506         act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M;
 1507         rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
 1508 
 1509         /* Use the filter rule ID of the previously created rule with single
 1510          * act. Once the update happens, hardware will treat this as large
 1511          * action
 1512          */
 1513         f_rule_id = m_ent->fltr_info.fltr_rule_id;
 1514         rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id);
 1515 
 1516         status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
 1517                                  ice_aqc_opc_update_sw_rules, NULL);
 1518         if (!status) {
 1519                 m_ent->lg_act_idx = l_id;
 1520                 m_ent->counter_index = counter_id;
 1521         }
 1522 
 1523         ice_free(hw, lg_act);
 1524         return status;
 1525 }
 1526 
 1527 /**
 1528  * ice_create_vsi_list_map
 1529  * @hw: pointer to the hardware structure
 1530  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
 1531  * @num_vsi: number of VSI handles in the array
 1532  * @vsi_list_id: VSI list ID generated as part of allocate resource
 1533  *
 1534  * Helper function to create a new entry of VSI list ID to VSI mapping
 1535  * using the given VSI list ID
 1536  */
 1537 static struct ice_vsi_list_map_info *
 1538 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
 1539                         u16 vsi_list_id)
 1540 {
 1541         struct ice_switch_info *sw = hw->switch_info;
 1542         struct ice_vsi_list_map_info *v_map;
 1543         int i;
 1544 
 1545         v_map = (struct ice_vsi_list_map_info *)ice_malloc(hw, sizeof(*v_map));
 1546         if (!v_map)
 1547                 return NULL;
 1548 
 1549         v_map->vsi_list_id = vsi_list_id;
 1550         v_map->ref_cnt = 1;
 1551         for (i = 0; i < num_vsi; i++)
 1552                 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map);
 1553 
 1554         LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head);
 1555         return v_map;
 1556 }
 1557 
 1558 /**
 1559  * ice_update_vsi_list_rule
 1560  * @hw: pointer to the hardware structure
 1561  * @vsi_handle_arr: array of VSI handles to form a VSI list
 1562  * @num_vsi: number of VSI handles in the array
 1563  * @vsi_list_id: VSI list ID generated as part of allocate resource
 1564  * @remove: Boolean value to indicate if this is a remove action
 1565  * @opc: switch rules population command type - pass in the command opcode
 1566  * @lkup_type: lookup type of the filter
 1567  *
 1568  * Call AQ command to add a new switch rule or update existing switch rule
 1569  * using the given VSI list ID
 1570  */
 1571 static enum ice_status
 1572 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
 1573                          u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
 1574                          enum ice_sw_lkup_type lkup_type)
 1575 {
 1576         struct ice_aqc_sw_rules_elem *s_rule;
 1577         enum ice_status status;
 1578         u16 s_rule_size;
 1579         u16 rule_type;
 1580         int i;
 1581 
 1582         if (!num_vsi)
 1583                 return ICE_ERR_PARAM;
 1584 
 1585         if (lkup_type == ICE_SW_LKUP_MAC ||
 1586             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
 1587             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
 1588             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
 1589             lkup_type == ICE_SW_LKUP_PROMISC ||
 1590             lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
 1591             lkup_type == ICE_SW_LKUP_LAST)
 1592                 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
 1593                         ICE_AQC_SW_RULES_T_VSI_LIST_SET;
 1594         else if (lkup_type == ICE_SW_LKUP_VLAN)
 1595                 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
 1596                         ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
 1597         else
 1598                 return ICE_ERR_PARAM;
 1599 
 1600         s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
 1601         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
 1602         if (!s_rule)
 1603                 return ICE_ERR_NO_MEMORY;
 1604         for (i = 0; i < num_vsi; i++) {
 1605                 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
 1606                         status = ICE_ERR_PARAM;
 1607                         goto exit;
 1608                 }
 1609                 /* AQ call requires hw_vsi_id(s) */
 1610                 s_rule->pdata.vsi_list.vsi[i] =
 1611                         CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
 1612         }
 1613 
 1614         s_rule->type = CPU_TO_LE16(rule_type);
 1615         s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi);
 1616         s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
 1617 
 1618         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
 1619 
 1620 exit:
 1621         ice_free(hw, s_rule);
 1622         return status;
 1623 }
 1624 
 1625 /**
 1626  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
 1627  * @hw: pointer to the HW struct
 1628  * @vsi_handle_arr: array of VSI handles to form a VSI list
 1629  * @num_vsi: number of VSI handles in the array
 1630  * @vsi_list_id: stores the ID of the VSI list to be created
 1631  * @lkup_type: switch rule filter's lookup type
 1632  */
 1633 static enum ice_status
 1634 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
 1635                          u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
 1636 {
 1637         enum ice_status status;
 1638 
 1639         status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
 1640                                             ice_aqc_opc_alloc_res);
 1641         if (status)
 1642                 return status;
 1643 
 1644         /* Update the newly created VSI list to include the specified VSIs */
 1645         return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
 1646                                         *vsi_list_id, false,
 1647                                         ice_aqc_opc_add_sw_rules, lkup_type);
 1648 }
 1649 
 1650 /**
 1651  * ice_create_pkt_fwd_rule
 1652  * @hw: pointer to the hardware structure
 1653  * @recp_list: corresponding filter management list
 1654  * @f_entry: entry containing packet forwarding information
 1655  *
 1656  * Create switch rule with given filter information and add an entry
 1657  * to the corresponding filter management list to track this switch rule
 1658  * and VSI mapping
 1659  */
 1660 static enum ice_status
 1661 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
 1662                         struct ice_fltr_list_entry *f_entry)
 1663 {
 1664         struct ice_fltr_mgmt_list_entry *fm_entry;
 1665         struct ice_aqc_sw_rules_elem *s_rule;
 1666         enum ice_status status;
 1667 
 1668         s_rule = (struct ice_aqc_sw_rules_elem *)
 1669                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
 1670         if (!s_rule)
 1671                 return ICE_ERR_NO_MEMORY;
 1672         fm_entry = (struct ice_fltr_mgmt_list_entry *)
 1673                    ice_malloc(hw, sizeof(*fm_entry));
 1674         if (!fm_entry) {
 1675                 status = ICE_ERR_NO_MEMORY;
 1676                 goto ice_create_pkt_fwd_rule_exit;
 1677         }
 1678 
 1679         fm_entry->fltr_info = f_entry->fltr_info;
 1680 
 1681         /* Initialize all the fields for the management entry */
 1682         fm_entry->vsi_count = 1;
 1683         fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
 1684         fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
 1685         fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
 1686 
 1687         ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
 1688                          ice_aqc_opc_add_sw_rules);
 1689 
 1690         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
 1691                                  ice_aqc_opc_add_sw_rules, NULL);
 1692         if (status) {
 1693                 ice_free(hw, fm_entry);
 1694                 goto ice_create_pkt_fwd_rule_exit;
 1695         }
 1696 
 1697         f_entry->fltr_info.fltr_rule_id =
 1698                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
 1699         fm_entry->fltr_info.fltr_rule_id =
 1700                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
 1701 
 1702         /* The book keeping entries will get removed when base driver
 1703          * calls remove filter AQ command
 1704          */
 1705         LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules);
 1706 
 1707 ice_create_pkt_fwd_rule_exit:
 1708         ice_free(hw, s_rule);
 1709         return status;
 1710 }
 1711 
 1712 /**
 1713  * ice_update_pkt_fwd_rule
 1714  * @hw: pointer to the hardware structure
 1715  * @f_info: filter information for switch rule
 1716  *
 1717  * Call AQ command to update a previously created switch rule with a
 1718  * VSI list ID
 1719  */
 1720 static enum ice_status
 1721 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
 1722 {
 1723         struct ice_aqc_sw_rules_elem *s_rule;
 1724         enum ice_status status;
 1725 
 1726         s_rule = (struct ice_aqc_sw_rules_elem *)
 1727                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
 1728         if (!s_rule)
 1729                 return ICE_ERR_NO_MEMORY;
 1730 
 1731         ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
 1732 
 1733         s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id);
 1734 
 1735         /* Update switch rule with new rule set to forward VSI list */
 1736         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
 1737                                  ice_aqc_opc_update_sw_rules, NULL);
 1738 
 1739         ice_free(hw, s_rule);
 1740         return status;
 1741 }
 1742 
 1743 /**
 1744  * ice_update_sw_rule_bridge_mode
 1745  * @hw: pointer to the HW struct
 1746  *
 1747  * Updates unicast switch filter rules based on VEB/VEPA mode
 1748  */
 1749 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
 1750 {
 1751         struct ice_switch_info *sw = hw->switch_info;
 1752         struct ice_fltr_mgmt_list_entry *fm_entry;
 1753         enum ice_status status = ICE_SUCCESS;
 1754         struct LIST_HEAD_TYPE *rule_head;
 1755         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 1756 
 1757         rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
 1758         rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
 1759 
 1760         ice_acquire_lock(rule_lock);
 1761         LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry,
 1762                             list_entry) {
 1763                 struct ice_fltr_info *fi = &fm_entry->fltr_info;
 1764                 u8 *addr = fi->l_data.mac.mac_addr;
 1765 
 1766                 /* Update unicast Tx rules to reflect the selected
 1767                  * VEB/VEPA mode
 1768                  */
 1769                 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) &&
 1770                     (fi->fltr_act == ICE_FWD_TO_VSI ||
 1771                      fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
 1772                      fi->fltr_act == ICE_FWD_TO_Q ||
 1773                      fi->fltr_act == ICE_FWD_TO_QGRP)) {
 1774                         status = ice_update_pkt_fwd_rule(hw, fi);
 1775                         if (status)
 1776                                 break;
 1777                 }
 1778         }
 1779 
 1780         ice_release_lock(rule_lock);
 1781 
 1782         return status;
 1783 }
 1784 
 1785 /**
 1786  * ice_add_update_vsi_list
 1787  * @hw: pointer to the hardware structure
 1788  * @m_entry: pointer to current filter management list entry
 1789  * @cur_fltr: filter information from the book keeping entry
 1790  * @new_fltr: filter information with the new VSI to be added
 1791  *
 1792  * Call AQ command to add or update previously created VSI list with new VSI.
 1793  *
 1794  * Helper function to do book keeping associated with adding filter information
 1795  * The algorithm to do the book keeping is described below :
 1796  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
 1797  *      if only one VSI has been added till now
 1798  *              Allocate a new VSI list and add two VSIs
 1799  *              to this list using switch rule command
 1800  *              Update the previously created switch rule with the
 1801  *              newly created VSI list ID
 1802  *      if a VSI list was previously created
 1803  *              Add the new VSI to the previously created VSI list set
 1804  *              using the update switch rule command
 1805  */
 1806 static enum ice_status
 1807 ice_add_update_vsi_list(struct ice_hw *hw,
 1808                         struct ice_fltr_mgmt_list_entry *m_entry,
 1809                         struct ice_fltr_info *cur_fltr,
 1810                         struct ice_fltr_info *new_fltr)
 1811 {
 1812         enum ice_status status = ICE_SUCCESS;
 1813         u16 vsi_list_id = 0;
 1814 
 1815         if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
 1816              cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
 1817                 return ICE_ERR_NOT_IMPL;
 1818 
 1819         if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
 1820              new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
 1821             (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
 1822              cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
 1823                 return ICE_ERR_NOT_IMPL;
 1824 
 1825         if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
 1826                 /* Only one entry existed in the mapping and it was not already
 1827                  * a part of a VSI list. So, create a VSI list with the old and
 1828                  * new VSIs.
 1829                  */
 1830                 struct ice_fltr_info tmp_fltr;
 1831                 u16 vsi_handle_arr[2];
 1832 
 1833                 /* A rule already exists with the new VSI being added */
 1834                 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
 1835                         return ICE_ERR_ALREADY_EXISTS;
 1836 
 1837                 vsi_handle_arr[0] = cur_fltr->vsi_handle;
 1838                 vsi_handle_arr[1] = new_fltr->vsi_handle;
 1839                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
 1840                                                   &vsi_list_id,
 1841                                                   new_fltr->lkup_type);
 1842                 if (status)
 1843                         return status;
 1844 
 1845                 tmp_fltr = *new_fltr;
 1846                 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
 1847                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
 1848                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
 1849                 /* Update the previous switch rule of "MAC forward to VSI" to
 1850                  * "MAC fwd to VSI list"
 1851                  */
 1852                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
 1853                 if (status)
 1854                         return status;
 1855 
 1856                 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
 1857                 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
 1858                 m_entry->vsi_list_info =
 1859                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
 1860                                                 vsi_list_id);
 1861 
 1862                 if (!m_entry->vsi_list_info)
 1863                         return ICE_ERR_NO_MEMORY;
 1864 
 1865                 /* If this entry was large action then the large action needs
 1866                  * to be updated to point to FWD to VSI list
 1867                  */
 1868                 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
 1869                         status =
 1870                             ice_add_marker_act(hw, m_entry,
 1871                                                m_entry->sw_marker_id,
 1872                                                m_entry->lg_act_idx);
 1873         } else {
 1874                 u16 vsi_handle = new_fltr->vsi_handle;
 1875                 enum ice_adminq_opc opcode;
 1876 
 1877                 if (!m_entry->vsi_list_info)
 1878                         return ICE_ERR_CFG;
 1879 
 1880                 /* A rule already exists with the new VSI being added */
 1881                 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
 1882                         return ICE_SUCCESS;
 1883 
 1884                 /* Update the previously created VSI list set with
 1885                  * the new VSI ID passed in
 1886                  */
 1887                 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
 1888                 opcode = ice_aqc_opc_update_sw_rules;
 1889 
 1890                 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
 1891                                                   vsi_list_id, false, opcode,
 1892                                                   new_fltr->lkup_type);
 1893                 /* update VSI list mapping info with new VSI ID */
 1894                 if (!status)
 1895                         ice_set_bit(vsi_handle,
 1896                                     m_entry->vsi_list_info->vsi_map);
 1897         }
 1898         if (!status)
 1899                 m_entry->vsi_count++;
 1900         return status;
 1901 }
 1902 
 1903 /**
 1904  * ice_find_rule_entry - Search a rule entry
 1905  * @list_head: head of rule list
 1906  * @f_info: rule information
 1907  *
 1908  * Helper function to search for a given rule entry
 1909  * Returns pointer to entry storing the rule if found
 1910  */
 1911 static struct ice_fltr_mgmt_list_entry *
 1912 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head,
 1913                     struct ice_fltr_info *f_info)
 1914 {
 1915         struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
 1916 
 1917         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
 1918                             list_entry) {
 1919                 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
 1920                             sizeof(f_info->l_data)) &&
 1921                     f_info->flag == list_itr->fltr_info.flag) {
 1922                         ret = list_itr;
 1923                         break;
 1924                 }
 1925         }
 1926         return ret;
 1927 }
 1928 
 1929 /**
 1930  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
 1931  * @recp_list: VSI lists needs to be searched
 1932  * @vsi_handle: VSI handle to be found in VSI list
 1933  * @vsi_list_id: VSI list ID found containing vsi_handle
 1934  *
 1935  * Helper function to search a VSI list with single entry containing given VSI
 1936  * handle element. This can be extended further to search VSI list with more
 1937  * than 1 vsi_count. Returns pointer to VSI list entry if found.
 1938  */
 1939 static struct ice_vsi_list_map_info *
 1940 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle,
 1941                         u16 *vsi_list_id)
 1942 {
 1943         struct ice_vsi_list_map_info *map_info = NULL;
 1944         struct LIST_HEAD_TYPE *list_head;
 1945 
 1946         list_head = &recp_list->filt_rules;
 1947         if (recp_list->adv_rule) {
 1948                 struct ice_adv_fltr_mgmt_list_entry *list_itr;
 1949 
 1950                 LIST_FOR_EACH_ENTRY(list_itr, list_head,
 1951                                     ice_adv_fltr_mgmt_list_entry,
 1952                                     list_entry) {
 1953                         if (list_itr->vsi_list_info) {
 1954                                 map_info = list_itr->vsi_list_info;
 1955                                 if (ice_is_bit_set(map_info->vsi_map,
 1956                                                    vsi_handle)) {
 1957                                         *vsi_list_id = map_info->vsi_list_id;
 1958                                         return map_info;
 1959                                 }
 1960                         }
 1961                 }
 1962         } else {
 1963                 struct ice_fltr_mgmt_list_entry *list_itr;
 1964 
 1965                 LIST_FOR_EACH_ENTRY(list_itr, list_head,
 1966                                     ice_fltr_mgmt_list_entry,
 1967                                     list_entry) {
 1968                         if (list_itr->vsi_count == 1 &&
 1969                             list_itr->vsi_list_info) {
 1970                                 map_info = list_itr->vsi_list_info;
 1971                                 if (ice_is_bit_set(map_info->vsi_map,
 1972                                                    vsi_handle)) {
 1973                                         *vsi_list_id = map_info->vsi_list_id;
 1974                                         return map_info;
 1975                                 }
 1976                         }
 1977                 }
 1978         }
 1979         return NULL;
 1980 }
 1981 
 1982 /**
 1983  * ice_add_rule_internal - add rule for a given lookup type
 1984  * @hw: pointer to the hardware structure
 1985  * @recp_list: recipe list for which rule has to be added
 1986  * @lport: logic port number on which function add rule
 1987  * @f_entry: structure containing MAC forwarding information
 1988  *
 1989  * Adds or updates the rule lists for a given recipe
 1990  */
 1991 static enum ice_status
 1992 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
 1993                       u8 lport, struct ice_fltr_list_entry *f_entry)
 1994 {
 1995         struct ice_fltr_info *new_fltr, *cur_fltr;
 1996         struct ice_fltr_mgmt_list_entry *m_entry;
 1997         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 1998         enum ice_status status = ICE_SUCCESS;
 1999 
 2000         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
 2001                 return ICE_ERR_PARAM;
 2002 
 2003         /* Load the hw_vsi_id only if the fwd action is fwd to VSI */
 2004         if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI)
 2005                 f_entry->fltr_info.fwd_id.hw_vsi_id =
 2006                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
 2007 
 2008         rule_lock = &recp_list->filt_rule_lock;
 2009 
 2010         ice_acquire_lock(rule_lock);
 2011         new_fltr = &f_entry->fltr_info;
 2012         if (new_fltr->flag & ICE_FLTR_RX)
 2013                 new_fltr->src = lport;
 2014         else if (new_fltr->flag & ICE_FLTR_TX)
 2015                 new_fltr->src =
 2016                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
 2017 
 2018         m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
 2019         if (!m_entry) {
 2020                 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
 2021                 goto exit_add_rule_internal;
 2022         }
 2023 
 2024         cur_fltr = &m_entry->fltr_info;
 2025         status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
 2026 
 2027 exit_add_rule_internal:
 2028         ice_release_lock(rule_lock);
 2029         return status;
 2030 }
 2031 
 2032 /**
 2033  * ice_remove_vsi_list_rule
 2034  * @hw: pointer to the hardware structure
 2035  * @vsi_list_id: VSI list ID generated as part of allocate resource
 2036  * @lkup_type: switch rule filter lookup type
 2037  *
 2038  * The VSI list should be emptied before this function is called to remove the
 2039  * VSI list.
 2040  */
 2041 static enum ice_status
 2042 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
 2043                          enum ice_sw_lkup_type lkup_type)
 2044 {
 2045         /* Free the vsi_list resource that we allocated. It is assumed that the
 2046          * list is empty at this point.
 2047          */
 2048         return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
 2049                                             ice_aqc_opc_free_res);
 2050 }
 2051 
 2052 /**
 2053  * ice_rem_update_vsi_list
 2054  * @hw: pointer to the hardware structure
 2055  * @vsi_handle: VSI handle of the VSI to remove
 2056  * @fm_list: filter management entry for which the VSI list management needs to
 2057  *           be done
 2058  */
 2059 static enum ice_status
 2060 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
 2061                         struct ice_fltr_mgmt_list_entry *fm_list)
 2062 {
 2063         enum ice_sw_lkup_type lkup_type;
 2064         enum ice_status status = ICE_SUCCESS;
 2065         u16 vsi_list_id;
 2066 
 2067         if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
 2068             fm_list->vsi_count == 0)
 2069                 return ICE_ERR_PARAM;
 2070 
 2071         /* A rule with the VSI being removed does not exist */
 2072         if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
 2073                 return ICE_ERR_DOES_NOT_EXIST;
 2074 
 2075         lkup_type = fm_list->fltr_info.lkup_type;
 2076         vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
 2077         status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
 2078                                           ice_aqc_opc_update_sw_rules,
 2079                                           lkup_type);
 2080         if (status)
 2081                 return status;
 2082 
 2083         fm_list->vsi_count--;
 2084         ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
 2085 
 2086         if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
 2087                 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
 2088                 struct ice_vsi_list_map_info *vsi_list_info =
 2089                         fm_list->vsi_list_info;
 2090                 u16 rem_vsi_handle;
 2091 
 2092                 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
 2093                                                     ICE_MAX_VSI);
 2094                 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
 2095                         return ICE_ERR_OUT_OF_RANGE;
 2096 
 2097                 /* Make sure VSI list is empty before removing it below */
 2098                 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
 2099                                                   vsi_list_id, true,
 2100                                                   ice_aqc_opc_update_sw_rules,
 2101                                                   lkup_type);
 2102                 if (status)
 2103                         return status;
 2104 
 2105                 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
 2106                 tmp_fltr_info.fwd_id.hw_vsi_id =
 2107                         ice_get_hw_vsi_num(hw, rem_vsi_handle);
 2108                 tmp_fltr_info.vsi_handle = rem_vsi_handle;
 2109                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
 2110                 if (status) {
 2111                         ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
 2112                                   tmp_fltr_info.fwd_id.hw_vsi_id, status);
 2113                         return status;
 2114                 }
 2115 
 2116                 fm_list->fltr_info = tmp_fltr_info;
 2117         }
 2118 
 2119         if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
 2120             (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
 2121                 struct ice_vsi_list_map_info *vsi_list_info =
 2122                         fm_list->vsi_list_info;
 2123 
 2124                 /* Remove the VSI list since it is no longer used */
 2125                 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
 2126                 if (status) {
 2127                         ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
 2128                                   vsi_list_id, status);
 2129                         return status;
 2130                 }
 2131 
 2132                 LIST_DEL(&vsi_list_info->list_entry);
 2133                 ice_free(hw, vsi_list_info);
 2134                 fm_list->vsi_list_info = NULL;
 2135         }
 2136 
 2137         return status;
 2138 }
 2139 
 2140 /**
 2141  * ice_remove_rule_internal - Remove a filter rule of a given type
 2142  *
 2143  * @hw: pointer to the hardware structure
 2144  * @recp_list: recipe list for which the rule needs to removed
 2145  * @f_entry: rule entry containing filter information
 2146  */
 2147 static enum ice_status
 2148 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
 2149                          struct ice_fltr_list_entry *f_entry)
 2150 {
 2151         struct ice_fltr_mgmt_list_entry *list_elem;
 2152         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 2153         enum ice_status status = ICE_SUCCESS;
 2154         bool remove_rule = false;
 2155         u16 vsi_handle;
 2156 
 2157         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
 2158                 return ICE_ERR_PARAM;
 2159         f_entry->fltr_info.fwd_id.hw_vsi_id =
 2160                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
 2161 
 2162         rule_lock = &recp_list->filt_rule_lock;
 2163         ice_acquire_lock(rule_lock);
 2164         list_elem = ice_find_rule_entry(&recp_list->filt_rules,
 2165                                         &f_entry->fltr_info);
 2166         if (!list_elem) {
 2167                 status = ICE_ERR_DOES_NOT_EXIST;
 2168                 goto exit;
 2169         }
 2170 
 2171         if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
 2172                 remove_rule = true;
 2173         } else if (!list_elem->vsi_list_info) {
 2174                 status = ICE_ERR_DOES_NOT_EXIST;
 2175                 goto exit;
 2176         } else if (list_elem->vsi_list_info->ref_cnt > 1) {
 2177                 /* a ref_cnt > 1 indicates that the vsi_list is being
 2178                  * shared by multiple rules. Decrement the ref_cnt and
 2179                  * remove this rule, but do not modify the list, as it
 2180                  * is in-use by other rules.
 2181                  */
 2182                 list_elem->vsi_list_info->ref_cnt--;
 2183                 remove_rule = true;
 2184         } else {
 2185                 /* a ref_cnt of 1 indicates the vsi_list is only used
 2186                  * by one rule. However, the original removal request is only
 2187                  * for a single VSI. Update the vsi_list first, and only
 2188                  * remove the rule if there are no further VSIs in this list.
 2189                  */
 2190                 vsi_handle = f_entry->fltr_info.vsi_handle;
 2191                 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
 2192                 if (status)
 2193                         goto exit;
 2194                 /* if VSI count goes to zero after updating the VSI list */
 2195                 if (list_elem->vsi_count == 0)
 2196                         remove_rule = true;
 2197         }
 2198 
 2199         if (remove_rule) {
 2200                 /* Remove the lookup rule */
 2201                 struct ice_aqc_sw_rules_elem *s_rule;
 2202 
 2203                 s_rule = (struct ice_aqc_sw_rules_elem *)
 2204                         ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE);
 2205                 if (!s_rule) {
 2206                         status = ICE_ERR_NO_MEMORY;
 2207                         goto exit;
 2208                 }
 2209 
 2210                 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
 2211                                  ice_aqc_opc_remove_sw_rules);
 2212 
 2213                 status = ice_aq_sw_rules(hw, s_rule,
 2214                                          ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
 2215                                          ice_aqc_opc_remove_sw_rules, NULL);
 2216 
 2217                 /* Remove a book keeping from the list */
 2218                 ice_free(hw, s_rule);
 2219 
 2220                 if (status)
 2221                         goto exit;
 2222 
 2223                 LIST_DEL(&list_elem->list_entry);
 2224                 ice_free(hw, list_elem);
 2225         }
 2226 exit:
 2227         ice_release_lock(rule_lock);
 2228         return status;
 2229 }
 2230 
 2231 /**
 2232  * ice_aq_get_res_alloc - get allocated resources
 2233  * @hw: pointer to the HW struct
 2234  * @num_entries: pointer to u16 to store the number of resource entries returned
 2235  * @buf: pointer to buffer
 2236  * @buf_size: size of buf
 2237  * @cd: pointer to command details structure or NULL
 2238  *
 2239  * The caller-supplied buffer must be large enough to store the resource
 2240  * information for all resource types. Each resource type is an
 2241  * ice_aqc_get_res_resp_elem structure.
 2242  */
 2243 enum ice_status
 2244 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries,
 2245                      struct ice_aqc_get_res_resp_elem *buf, u16 buf_size,
 2246                      struct ice_sq_cd *cd)
 2247 {
 2248         struct ice_aqc_get_res_alloc *resp;
 2249         enum ice_status status;
 2250         struct ice_aq_desc desc;
 2251 
 2252         if (!buf)
 2253                 return ICE_ERR_BAD_PTR;
 2254 
 2255         if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN)
 2256                 return ICE_ERR_INVAL_SIZE;
 2257 
 2258         resp = &desc.params.get_res;
 2259 
 2260         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc);
 2261         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
 2262 
 2263         if (!status && num_entries)
 2264                 *num_entries = LE16_TO_CPU(resp->resp_elem_num);
 2265 
 2266         return status;
 2267 }
 2268 
 2269 /**
 2270  * ice_aq_get_res_descs - get allocated resource descriptors
 2271  * @hw: pointer to the hardware structure
 2272  * @num_entries: number of resource entries in buffer
 2273  * @buf: structure to hold response data buffer
 2274  * @buf_size: size of buffer
 2275  * @res_type: resource type
 2276  * @res_shared: is resource shared
 2277  * @desc_id: input - first desc ID to start; output - next desc ID
 2278  * @cd: pointer to command details structure or NULL
 2279  */
 2280 enum ice_status
 2281 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
 2282                      struct ice_aqc_res_elem *buf, u16 buf_size, u16 res_type,
 2283                      bool res_shared, u16 *desc_id, struct ice_sq_cd *cd)
 2284 {
 2285         struct ice_aqc_get_allocd_res_desc *cmd;
 2286         struct ice_aq_desc desc;
 2287         enum ice_status status;
 2288 
 2289         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 2290 
 2291         cmd = &desc.params.get_res_desc;
 2292 
 2293         if (!buf)
 2294                 return ICE_ERR_PARAM;
 2295 
 2296         if (buf_size != (num_entries * sizeof(*buf)))
 2297                 return ICE_ERR_PARAM;
 2298 
 2299         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc);
 2300 
 2301         cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) &
 2302                                          ICE_AQC_RES_TYPE_M) | (res_shared ?
 2303                                         ICE_AQC_RES_TYPE_FLAG_SHARED : 0));
 2304         cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id);
 2305 
 2306         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
 2307         if (!status)
 2308                 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc);
 2309 
 2310         return status;
 2311 }
 2312 
 2313 /**
 2314  * ice_add_mac_rule - Add a MAC address based filter rule
 2315  * @hw: pointer to the hardware structure
 2316  * @m_list: list of MAC addresses and forwarding information
 2317  * @sw: pointer to switch info struct for which function add rule
 2318  * @lport: logic port number on which function add rule
 2319  *
 2320  * IMPORTANT: When the umac_shared flag is set to false and m_list has
 2321  * multiple unicast addresses, the function assumes that all the
 2322  * addresses are unique in a given add_mac call. It doesn't
 2323  * check for duplicates in this case, removing duplicates from a given
 2324  * list should be taken care of in the caller of this function.
 2325  */
 2326 static enum ice_status
 2327 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
 2328                  struct ice_switch_info *sw, u8 lport)
 2329 {
 2330         struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC];
 2331         struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
 2332         struct ice_fltr_list_entry *m_list_itr;
 2333         struct LIST_HEAD_TYPE *rule_head;
 2334         u16 total_elem_left, s_rule_size;
 2335         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 2336         enum ice_status status = ICE_SUCCESS;
 2337         u16 num_unicast = 0;
 2338         u8 elem_sent;
 2339 
 2340         s_rule = NULL;
 2341         rule_lock = &recp_list->filt_rule_lock;
 2342         rule_head = &recp_list->filt_rules;
 2343 
 2344         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
 2345                             list_entry) {
 2346                 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
 2347                 u16 vsi_handle;
 2348                 u16 hw_vsi_id;
 2349 
 2350                 m_list_itr->fltr_info.flag = ICE_FLTR_TX;
 2351                 vsi_handle = m_list_itr->fltr_info.vsi_handle;
 2352                 if (!ice_is_vsi_valid(hw, vsi_handle))
 2353                         return ICE_ERR_PARAM;
 2354                 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 2355                 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
 2356                 /* update the src in case it is VSI num */
 2357                 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
 2358                         return ICE_ERR_PARAM;
 2359                 m_list_itr->fltr_info.src = hw_vsi_id;
 2360                 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
 2361                     IS_ZERO_ETHER_ADDR(add))
 2362                         return ICE_ERR_PARAM;
 2363                 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) {
 2364                         /* Don't overwrite the unicast address */
 2365                         ice_acquire_lock(rule_lock);
 2366                         if (ice_find_rule_entry(rule_head,
 2367                                                 &m_list_itr->fltr_info)) {
 2368                                 ice_release_lock(rule_lock);
 2369                                 continue;
 2370                         }
 2371                         ice_release_lock(rule_lock);
 2372                         num_unicast++;
 2373                 } else if (IS_MULTICAST_ETHER_ADDR(add) ||
 2374                            (IS_UNICAST_ETHER_ADDR(add) && hw->umac_shared)) {
 2375                         m_list_itr->status =
 2376                                 ice_add_rule_internal(hw, recp_list, lport,
 2377                                                       m_list_itr);
 2378                         if (m_list_itr->status)
 2379                                 return m_list_itr->status;
 2380                 }
 2381         }
 2382 
 2383         ice_acquire_lock(rule_lock);
 2384         /* Exit if no suitable entries were found for adding bulk switch rule */
 2385         if (!num_unicast) {
 2386                 status = ICE_SUCCESS;
 2387                 goto ice_add_mac_exit;
 2388         }
 2389 
 2390         /* Allocate switch rule buffer for the bulk update for unicast */
 2391         s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
 2392         s_rule = (struct ice_aqc_sw_rules_elem *)
 2393                 ice_calloc(hw, num_unicast, s_rule_size);
 2394         if (!s_rule) {
 2395                 status = ICE_ERR_NO_MEMORY;
 2396                 goto ice_add_mac_exit;
 2397         }
 2398 
 2399         r_iter = s_rule;
 2400         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
 2401                             list_entry) {
 2402                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
 2403                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
 2404 
 2405                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
 2406                         ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
 2407                                          ice_aqc_opc_add_sw_rules);
 2408                         r_iter = (struct ice_aqc_sw_rules_elem *)
 2409                                 ((u8 *)r_iter + s_rule_size);
 2410                 }
 2411         }
 2412 
 2413         /* Call AQ bulk switch rule update for all unicast addresses */
 2414         r_iter = s_rule;
 2415         /* Call AQ switch rule in AQ_MAX chunk */
 2416         for (total_elem_left = num_unicast; total_elem_left > 0;
 2417              total_elem_left -= elem_sent) {
 2418                 struct ice_aqc_sw_rules_elem *entry = r_iter;
 2419 
 2420                 elem_sent = MIN_T(u8, total_elem_left,
 2421                                   (ICE_AQ_MAX_BUF_LEN / s_rule_size));
 2422                 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
 2423                                          elem_sent, ice_aqc_opc_add_sw_rules,
 2424                                          NULL);
 2425                 if (status)
 2426                         goto ice_add_mac_exit;
 2427                 r_iter = (struct ice_aqc_sw_rules_elem *)
 2428                         ((u8 *)r_iter + (elem_sent * s_rule_size));
 2429         }
 2430 
 2431         /* Fill up rule ID based on the value returned from FW */
 2432         r_iter = s_rule;
 2433         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
 2434                             list_entry) {
 2435                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
 2436                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
 2437                 struct ice_fltr_mgmt_list_entry *fm_entry;
 2438 
 2439                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
 2440                         f_info->fltr_rule_id =
 2441                                 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index);
 2442                         f_info->fltr_act = ICE_FWD_TO_VSI;
 2443                         /* Create an entry to track this MAC address */
 2444                         fm_entry = (struct ice_fltr_mgmt_list_entry *)
 2445                                 ice_malloc(hw, sizeof(*fm_entry));
 2446                         if (!fm_entry) {
 2447                                 status = ICE_ERR_NO_MEMORY;
 2448                                 goto ice_add_mac_exit;
 2449                         }
 2450                         fm_entry->fltr_info = *f_info;
 2451                         fm_entry->vsi_count = 1;
 2452                         /* The book keeping entries will get removed when
 2453                          * base driver calls remove filter AQ command
 2454                          */
 2455 
 2456                         LIST_ADD(&fm_entry->list_entry, rule_head);
 2457                         r_iter = (struct ice_aqc_sw_rules_elem *)
 2458                                 ((u8 *)r_iter + s_rule_size);
 2459                 }
 2460         }
 2461 
 2462 ice_add_mac_exit:
 2463         ice_release_lock(rule_lock);
 2464         if (s_rule)
 2465                 ice_free(hw, s_rule);
 2466         return status;
 2467 }
 2468 
 2469 /**
 2470  * ice_add_mac - Add a MAC address based filter rule
 2471  * @hw: pointer to the hardware structure
 2472  * @m_list: list of MAC addresses and forwarding information
 2473  *
 2474  * Function add MAC rule for logical port from HW struct
 2475  */
 2476 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
 2477 {
 2478         if (!m_list || !hw)
 2479                 return ICE_ERR_PARAM;
 2480 
 2481         return ice_add_mac_rule(hw, m_list, hw->switch_info,
 2482                                 hw->port_info->lport);
 2483 }
 2484 
 2485 /**
 2486  * ice_add_vlan_internal - Add one VLAN based filter rule
 2487  * @hw: pointer to the hardware structure
 2488  * @recp_list: recipe list for which rule has to be added
 2489  * @f_entry: filter entry containing one VLAN information
 2490  */
 2491 static enum ice_status
 2492 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
 2493                       struct ice_fltr_list_entry *f_entry)
 2494 {
 2495         struct ice_fltr_mgmt_list_entry *v_list_itr;
 2496         struct ice_fltr_info *new_fltr, *cur_fltr;
 2497         enum ice_sw_lkup_type lkup_type;
 2498         u16 vsi_list_id = 0, vsi_handle;
 2499         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 2500         enum ice_status status = ICE_SUCCESS;
 2501 
 2502         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
 2503                 return ICE_ERR_PARAM;
 2504 
 2505         f_entry->fltr_info.fwd_id.hw_vsi_id =
 2506                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
 2507         new_fltr = &f_entry->fltr_info;
 2508 
 2509         /* VLAN ID should only be 12 bits */
 2510         if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
 2511                 return ICE_ERR_PARAM;
 2512 
 2513         if (new_fltr->src_id != ICE_SRC_ID_VSI)
 2514                 return ICE_ERR_PARAM;
 2515 
 2516         new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
 2517         lkup_type = new_fltr->lkup_type;
 2518         vsi_handle = new_fltr->vsi_handle;
 2519         rule_lock = &recp_list->filt_rule_lock;
 2520         ice_acquire_lock(rule_lock);
 2521         v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
 2522         if (!v_list_itr) {
 2523                 struct ice_vsi_list_map_info *map_info = NULL;
 2524 
 2525                 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
 2526                         /* All VLAN pruning rules use a VSI list. Check if
 2527                          * there is already a VSI list containing VSI that we
 2528                          * want to add. If found, use the same vsi_list_id for
 2529                          * this new VLAN rule or else create a new list.
 2530                          */
 2531                         map_info = ice_find_vsi_list_entry(recp_list,
 2532                                                            vsi_handle,
 2533                                                            &vsi_list_id);
 2534                         if (!map_info) {
 2535                                 status = ice_create_vsi_list_rule(hw,
 2536                                                                   &vsi_handle,
 2537                                                                   1,
 2538                                                                   &vsi_list_id,
 2539                                                                   lkup_type);
 2540                                 if (status)
 2541                                         goto exit;
 2542                         }
 2543                         /* Convert the action to forwarding to a VSI list. */
 2544                         new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
 2545                         new_fltr->fwd_id.vsi_list_id = vsi_list_id;
 2546                 }
 2547 
 2548                 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
 2549                 if (!status) {
 2550                         v_list_itr = ice_find_rule_entry(&recp_list->filt_rules,
 2551                                                          new_fltr);
 2552                         if (!v_list_itr) {
 2553                                 status = ICE_ERR_DOES_NOT_EXIST;
 2554                                 goto exit;
 2555                         }
 2556                         /* reuse VSI list for new rule and increment ref_cnt */
 2557                         if (map_info) {
 2558                                 v_list_itr->vsi_list_info = map_info;
 2559                                 map_info->ref_cnt++;
 2560                         } else {
 2561                                 v_list_itr->vsi_list_info =
 2562                                         ice_create_vsi_list_map(hw, &vsi_handle,
 2563                                                                 1, vsi_list_id);
 2564                         }
 2565                 }
 2566         } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
 2567                 /* Update existing VSI list to add new VSI ID only if it used
 2568                  * by one VLAN rule.
 2569                  */
 2570                 cur_fltr = &v_list_itr->fltr_info;
 2571                 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
 2572                                                  new_fltr);
 2573         } else {
 2574                 /* If VLAN rule exists and VSI list being used by this rule is
 2575                  * referenced by more than 1 VLAN rule. Then create a new VSI
 2576                  * list appending previous VSI with new VSI and update existing
 2577                  * VLAN rule to point to new VSI list ID
 2578                  */
 2579                 struct ice_fltr_info tmp_fltr;
 2580                 u16 vsi_handle_arr[2];
 2581                 u16 cur_handle;
 2582 
 2583                 /* Current implementation only supports reusing VSI list with
 2584                  * one VSI count. We should never hit below condition
 2585                  */
 2586                 if (v_list_itr->vsi_count > 1 &&
 2587                     v_list_itr->vsi_list_info->ref_cnt > 1) {
 2588                         ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
 2589                         status = ICE_ERR_CFG;
 2590                         goto exit;
 2591                 }
 2592 
 2593                 cur_handle =
 2594                         ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map,
 2595                                            ICE_MAX_VSI);
 2596 
 2597                 /* A rule already exists with the new VSI being added */
 2598                 if (cur_handle == vsi_handle) {
 2599                         status = ICE_ERR_ALREADY_EXISTS;
 2600                         goto exit;
 2601                 }
 2602 
 2603                 vsi_handle_arr[0] = cur_handle;
 2604                 vsi_handle_arr[1] = vsi_handle;
 2605                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
 2606                                                   &vsi_list_id, lkup_type);
 2607                 if (status)
 2608                         goto exit;
 2609 
 2610                 tmp_fltr = v_list_itr->fltr_info;
 2611                 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
 2612                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
 2613                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
 2614                 /* Update the previous switch rule to a new VSI list which
 2615                  * includes current VSI that is requested
 2616                  */
 2617                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
 2618                 if (status)
 2619                         goto exit;
 2620 
 2621                 /* before overriding VSI list map info. decrement ref_cnt of
 2622                  * previous VSI list
 2623                  */
 2624                 v_list_itr->vsi_list_info->ref_cnt--;
 2625 
 2626                 /* now update to newly created list */
 2627                 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
 2628                 v_list_itr->vsi_list_info =
 2629                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
 2630                                                 vsi_list_id);
 2631                 v_list_itr->vsi_count++;
 2632         }
 2633 
 2634 exit:
 2635         ice_release_lock(rule_lock);
 2636         return status;
 2637 }
 2638 
 2639 /**
 2640  * ice_add_vlan_rule - Add VLAN based filter rule
 2641  * @hw: pointer to the hardware structure
 2642  * @v_list: list of VLAN entries and forwarding information
 2643  * @sw: pointer to switch info struct for which function add rule
 2644  */
 2645 static enum ice_status
 2646 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
 2647                   struct ice_switch_info *sw)
 2648 {
 2649         struct ice_fltr_list_entry *v_list_itr;
 2650         struct ice_sw_recipe *recp_list;
 2651 
 2652         recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN];
 2653         LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry,
 2654                             list_entry) {
 2655                 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
 2656                         return ICE_ERR_PARAM;
 2657                 v_list_itr->fltr_info.flag = ICE_FLTR_TX;
 2658                 v_list_itr->status = ice_add_vlan_internal(hw, recp_list,
 2659                                                            v_list_itr);
 2660                 if (v_list_itr->status)
 2661                         return v_list_itr->status;
 2662         }
 2663         return ICE_SUCCESS;
 2664 }
 2665 
 2666 /**
 2667  * ice_add_vlan - Add a VLAN based filter rule
 2668  * @hw: pointer to the hardware structure
 2669  * @v_list: list of VLAN and forwarding information
 2670  *
 2671  * Function add VLAN rule for logical port from HW struct
 2672  */
 2673 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
 2674 {
 2675         if (!v_list || !hw)
 2676                 return ICE_ERR_PARAM;
 2677 
 2678         return ice_add_vlan_rule(hw, v_list, hw->switch_info);
 2679 }
 2680 
 2681 /**
 2682  * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule
 2683  * @hw: pointer to the hardware structure
 2684  * @em_list: list of ether type MAC filter, MAC is optional
 2685  * @sw: pointer to switch info struct for which function add rule
 2686  * @lport: logic port number on which function add rule
 2687  *
 2688  * This function requires the caller to populate the entries in
 2689  * the filter list with the necessary fields (including flags to
 2690  * indicate Tx or Rx rules).
 2691  */
 2692 static enum ice_status
 2693 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
 2694                      struct ice_switch_info *sw, u8 lport)
 2695 {
 2696         struct ice_fltr_list_entry *em_list_itr;
 2697 
 2698         LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry,
 2699                             list_entry) {
 2700                 struct ice_sw_recipe *recp_list;
 2701                 enum ice_sw_lkup_type l_type;
 2702 
 2703                 l_type = em_list_itr->fltr_info.lkup_type;
 2704                 recp_list = &sw->recp_list[l_type];
 2705 
 2706                 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
 2707                     l_type != ICE_SW_LKUP_ETHERTYPE)
 2708                         return ICE_ERR_PARAM;
 2709 
 2710                 em_list_itr->status = ice_add_rule_internal(hw, recp_list,
 2711                                                             lport,
 2712                                                             em_list_itr);
 2713                 if (em_list_itr->status)
 2714                         return em_list_itr->status;
 2715         }
 2716         return ICE_SUCCESS;
 2717 }
 2718 
 2719 /**
 2720  * ice_add_eth_mac - Add a ethertype based filter rule
 2721  * @hw: pointer to the hardware structure
 2722  * @em_list: list of ethertype and forwarding information
 2723  *
 2724  * Function add ethertype rule for logical port from HW struct
 2725  */
 2726 enum ice_status
 2727 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
 2728 {
 2729         if (!em_list || !hw)
 2730                 return ICE_ERR_PARAM;
 2731 
 2732         return ice_add_eth_mac_rule(hw, em_list, hw->switch_info,
 2733                                     hw->port_info->lport);
 2734 }
 2735 
 2736 /**
 2737  * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule
 2738  * @hw: pointer to the hardware structure
 2739  * @em_list: list of ethertype or ethertype MAC entries
 2740  * @sw: pointer to switch info struct for which function add rule
 2741  */
 2742 static enum ice_status
 2743 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
 2744                         struct ice_switch_info *sw)
 2745 {
 2746         struct ice_fltr_list_entry *em_list_itr, *tmp;
 2747 
 2748         LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry,
 2749                                  list_entry) {
 2750                 struct ice_sw_recipe *recp_list;
 2751                 enum ice_sw_lkup_type l_type;
 2752 
 2753                 l_type = em_list_itr->fltr_info.lkup_type;
 2754 
 2755                 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
 2756                     l_type != ICE_SW_LKUP_ETHERTYPE)
 2757                         return ICE_ERR_PARAM;
 2758 
 2759                 recp_list = &sw->recp_list[l_type];
 2760                 em_list_itr->status = ice_remove_rule_internal(hw, recp_list,
 2761                                                                em_list_itr);
 2762                 if (em_list_itr->status)
 2763                         return em_list_itr->status;
 2764         }
 2765         return ICE_SUCCESS;
 2766 }
 2767 
 2768 /**
 2769  * ice_remove_eth_mac - remove a ethertype based filter rule
 2770  * @hw: pointer to the hardware structure
 2771  * @em_list: list of ethertype and forwarding information
 2772  *
 2773  */
 2774 enum ice_status
 2775 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
 2776 {
 2777         if (!em_list || !hw)
 2778                 return ICE_ERR_PARAM;
 2779 
 2780         return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info);
 2781 }
 2782 
 2783 /**
 2784  * ice_rem_sw_rule_info
 2785  * @hw: pointer to the hardware structure
 2786  * @rule_head: pointer to the switch list structure that we want to delete
 2787  */
 2788 static void
 2789 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
 2790 {
 2791         if (!LIST_EMPTY(rule_head)) {
 2792                 struct ice_fltr_mgmt_list_entry *entry;
 2793                 struct ice_fltr_mgmt_list_entry *tmp;
 2794 
 2795                 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head,
 2796                                          ice_fltr_mgmt_list_entry, list_entry) {
 2797                         LIST_DEL(&entry->list_entry);
 2798                         ice_free(hw, entry);
 2799                 }
 2800         }
 2801 }
 2802 
 2803 /**
 2804  * ice_rem_all_sw_rules_info
 2805  * @hw: pointer to the hardware structure
 2806  */
 2807 void ice_rem_all_sw_rules_info(struct ice_hw *hw)
 2808 {
 2809         struct ice_switch_info *sw = hw->switch_info;
 2810         u8 i;
 2811 
 2812         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
 2813                 struct LIST_HEAD_TYPE *rule_head;
 2814 
 2815                 rule_head = &sw->recp_list[i].filt_rules;
 2816                 if (!sw->recp_list[i].adv_rule)
 2817                         ice_rem_sw_rule_info(hw, rule_head);
 2818         }
 2819 }
 2820 
 2821 /**
 2822  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
 2823  * @pi: pointer to the port_info structure
 2824  * @vsi_handle: VSI handle to set as default
 2825  * @set: true to add the above mentioned switch rule, false to remove it
 2826  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
 2827  *
 2828  * add filter rule to set/unset given VSI as default VSI for the switch
 2829  * (represented by swid)
 2830  */
 2831 enum ice_status
 2832 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
 2833                  u8 direction)
 2834 {
 2835         struct ice_aqc_sw_rules_elem *s_rule;
 2836         struct ice_fltr_info f_info;
 2837         struct ice_hw *hw = pi->hw;
 2838         enum ice_adminq_opc opcode;
 2839         enum ice_status status;
 2840         u16 s_rule_size;
 2841         u16 hw_vsi_id;
 2842 
 2843         if (!ice_is_vsi_valid(hw, vsi_handle))
 2844                 return ICE_ERR_PARAM;
 2845         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 2846 
 2847         s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
 2848                 ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
 2849 
 2850         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
 2851         if (!s_rule)
 2852                 return ICE_ERR_NO_MEMORY;
 2853 
 2854         ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM);
 2855 
 2856         f_info.lkup_type = ICE_SW_LKUP_DFLT;
 2857         f_info.flag = direction;
 2858         f_info.fltr_act = ICE_FWD_TO_VSI;
 2859         f_info.fwd_id.hw_vsi_id = hw_vsi_id;
 2860 
 2861         if (f_info.flag & ICE_FLTR_RX) {
 2862                 f_info.src = pi->lport;
 2863                 f_info.src_id = ICE_SRC_ID_LPORT;
 2864                 if (!set)
 2865                         f_info.fltr_rule_id =
 2866                                 pi->dflt_rx_vsi_rule_id;
 2867         } else if (f_info.flag & ICE_FLTR_TX) {
 2868                 f_info.src_id = ICE_SRC_ID_VSI;
 2869                 f_info.src = hw_vsi_id;
 2870                 if (!set)
 2871                         f_info.fltr_rule_id =
 2872                                 pi->dflt_tx_vsi_rule_id;
 2873         }
 2874 
 2875         if (set)
 2876                 opcode = ice_aqc_opc_add_sw_rules;
 2877         else
 2878                 opcode = ice_aqc_opc_remove_sw_rules;
 2879 
 2880         ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
 2881 
 2882         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
 2883         if (status || !(f_info.flag & ICE_FLTR_TX_RX))
 2884                 goto out;
 2885         if (set) {
 2886                 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
 2887 
 2888                 if (f_info.flag & ICE_FLTR_TX) {
 2889                         pi->dflt_tx_vsi_num = hw_vsi_id;
 2890                         pi->dflt_tx_vsi_rule_id = index;
 2891                 } else if (f_info.flag & ICE_FLTR_RX) {
 2892                         pi->dflt_rx_vsi_num = hw_vsi_id;
 2893                         pi->dflt_rx_vsi_rule_id = index;
 2894                 }
 2895         } else {
 2896                 if (f_info.flag & ICE_FLTR_TX) {
 2897                         pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
 2898                         pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
 2899                 } else if (f_info.flag & ICE_FLTR_RX) {
 2900                         pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
 2901                         pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
 2902                 }
 2903         }
 2904 
 2905 out:
 2906         ice_free(hw, s_rule);
 2907         return status;
 2908 }
 2909 
 2910 /**
 2911  * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
 2912  * @list_head: head of rule list
 2913  * @f_info: rule information
 2914  *
 2915  * Helper function to search for a unicast rule entry - this is to be used
 2916  * to remove unicast MAC filter that is not shared with other VSIs on the
 2917  * PF switch.
 2918  *
 2919  * Returns pointer to entry storing the rule if found
 2920  */
 2921 static struct ice_fltr_mgmt_list_entry *
 2922 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head,
 2923                           struct ice_fltr_info *f_info)
 2924 {
 2925         struct ice_fltr_mgmt_list_entry *list_itr;
 2926 
 2927         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
 2928                             list_entry) {
 2929                 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
 2930                             sizeof(f_info->l_data)) &&
 2931                     f_info->fwd_id.hw_vsi_id ==
 2932                     list_itr->fltr_info.fwd_id.hw_vsi_id &&
 2933                     f_info->flag == list_itr->fltr_info.flag)
 2934                         return list_itr;
 2935         }
 2936         return NULL;
 2937 }
 2938 
 2939 /**
 2940  * ice_remove_mac_rule - remove a MAC based filter rule
 2941  * @hw: pointer to the hardware structure
 2942  * @m_list: list of MAC addresses and forwarding information
 2943  * @recp_list: list from which function remove MAC address
 2944  *
 2945  * This function removes either a MAC filter rule or a specific VSI from a
 2946  * VSI list for a multicast MAC address.
 2947  *
 2948  * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
 2949  * ice_add_mac. Caller should be aware that this call will only work if all
 2950  * the entries passed into m_list were added previously. It will not attempt to
 2951  * do a partial remove of entries that were found.
 2952  */
 2953 static enum ice_status
 2954 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
 2955                     struct ice_sw_recipe *recp_list)
 2956 {
 2957         struct ice_fltr_list_entry *list_itr, *tmp;
 2958         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
 2959 
 2960         if (!m_list)
 2961                 return ICE_ERR_PARAM;
 2962 
 2963         rule_lock = &recp_list->filt_rule_lock;
 2964         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry,
 2965                                  list_entry) {
 2966                 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
 2967                 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
 2968                 u16 vsi_handle;
 2969 
 2970                 if (l_type != ICE_SW_LKUP_MAC)
 2971                         return ICE_ERR_PARAM;
 2972 
 2973                 vsi_handle = list_itr->fltr_info.vsi_handle;
 2974                 if (!ice_is_vsi_valid(hw, vsi_handle))
 2975                         return ICE_ERR_PARAM;
 2976 
 2977                 list_itr->fltr_info.fwd_id.hw_vsi_id =
 2978                                         ice_get_hw_vsi_num(hw, vsi_handle);
 2979                 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) {
 2980                         /* Don't remove the unicast address that belongs to
 2981                          * another VSI on the switch, since it is not being
 2982                          * shared...
 2983                          */
 2984                         ice_acquire_lock(rule_lock);
 2985                         if (!ice_find_ucast_rule_entry(&recp_list->filt_rules,
 2986                                                        &list_itr->fltr_info)) {
 2987                                 ice_release_lock(rule_lock);
 2988                                 return ICE_ERR_DOES_NOT_EXIST;
 2989                         }
 2990                         ice_release_lock(rule_lock);
 2991                 }
 2992                 list_itr->status = ice_remove_rule_internal(hw, recp_list,
 2993                                                             list_itr);
 2994                 if (list_itr->status)
 2995                         return list_itr->status;
 2996         }
 2997         return ICE_SUCCESS;
 2998 }
 2999 
 3000 /**
 3001  * ice_remove_mac - remove a MAC address based filter rule
 3002  * @hw: pointer to the hardware structure
 3003  * @m_list: list of MAC addresses and forwarding information
 3004  *
 3005  */
 3006 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
 3007 {
 3008         struct ice_sw_recipe *recp_list;
 3009 
 3010         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
 3011         return ice_remove_mac_rule(hw, m_list, recp_list);
 3012 }
 3013 
 3014 /**
 3015  * ice_remove_vlan_rule - Remove VLAN based filter rule
 3016  * @hw: pointer to the hardware structure
 3017  * @v_list: list of VLAN entries and forwarding information
 3018  * @recp_list: list from which function remove VLAN
 3019  */
 3020 static enum ice_status
 3021 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
 3022                      struct ice_sw_recipe *recp_list)
 3023 {
 3024         struct ice_fltr_list_entry *v_list_itr, *tmp;
 3025 
 3026         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
 3027                                  list_entry) {
 3028                 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
 3029 
 3030                 if (l_type != ICE_SW_LKUP_VLAN)
 3031                         return ICE_ERR_PARAM;
 3032                 v_list_itr->status = ice_remove_rule_internal(hw, recp_list,
 3033                                                               v_list_itr);
 3034                 if (v_list_itr->status)
 3035                         return v_list_itr->status;
 3036         }
 3037         return ICE_SUCCESS;
 3038 }
 3039 
 3040 /**
 3041  * ice_remove_vlan - remove a VLAN address based filter rule
 3042  * @hw: pointer to the hardware structure
 3043  * @v_list: list of VLAN and forwarding information
 3044  *
 3045  */
 3046 enum ice_status
 3047 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
 3048 {
 3049         struct ice_sw_recipe *recp_list;
 3050 
 3051         if (!v_list || !hw)
 3052                 return ICE_ERR_PARAM;
 3053 
 3054         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN];
 3055         return ice_remove_vlan_rule(hw, v_list, recp_list);
 3056 }
 3057 
 3058 /**
 3059  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
 3060  * @fm_entry: filter entry to inspect
 3061  * @vsi_handle: VSI handle to compare with filter info
 3062  */
 3063 static bool
 3064 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
 3065 {
 3066         return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
 3067                  fm_entry->fltr_info.vsi_handle == vsi_handle) ||
 3068                 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
 3069                  fm_entry->vsi_list_info &&
 3070                  (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
 3071                                  vsi_handle))));
 3072 }
 3073 
 3074 /**
 3075  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
 3076  * @hw: pointer to the hardware structure
 3077  * @vsi_handle: VSI handle to remove filters from
 3078  * @vsi_list_head: pointer to the list to add entry to
 3079  * @fi: pointer to fltr_info of filter entry to copy & add
 3080  *
 3081  * Helper function, used when creating a list of filters to remove from
 3082  * a specific VSI. The entry added to vsi_list_head is a COPY of the
 3083  * original filter entry, with the exception of fltr_info.fltr_act and
 3084  * fltr_info.fwd_id fields. These are set such that later logic can
 3085  * extract which VSI to remove the fltr from, and pass on that information.
 3086  */
 3087 static enum ice_status
 3088 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
 3089                                struct LIST_HEAD_TYPE *vsi_list_head,
 3090                                struct ice_fltr_info *fi)
 3091 {
 3092         struct ice_fltr_list_entry *tmp;
 3093 
 3094         /* this memory is freed up in the caller function
 3095          * once filters for this VSI are removed
 3096          */
 3097         tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp));
 3098         if (!tmp)
 3099                 return ICE_ERR_NO_MEMORY;
 3100 
 3101         tmp->fltr_info = *fi;
 3102 
 3103         /* Overwrite these fields to indicate which VSI to remove filter from,
 3104          * so find and remove logic can extract the information from the
 3105          * list entries. Note that original entries will still have proper
 3106          * values.
 3107          */
 3108         tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
 3109         tmp->fltr_info.vsi_handle = vsi_handle;
 3110         tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 3111 
 3112         LIST_ADD(&tmp->list_entry, vsi_list_head);
 3113 
 3114         return ICE_SUCCESS;
 3115 }
 3116 
 3117 /**
 3118  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
 3119  * @hw: pointer to the hardware structure
 3120  * @vsi_handle: VSI handle to remove filters from
 3121  * @lkup_list_head: pointer to the list that has certain lookup type filters
 3122  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
 3123  *
 3124  * Locates all filters in lkup_list_head that are used by the given VSI,
 3125  * and adds COPIES of those entries to vsi_list_head (intended to be used
 3126  * to remove the listed filters).
 3127  * Note that this means all entries in vsi_list_head must be explicitly
 3128  * deallocated by the caller when done with list.
 3129  */
 3130 static enum ice_status
 3131 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
 3132                          struct LIST_HEAD_TYPE *lkup_list_head,
 3133                          struct LIST_HEAD_TYPE *vsi_list_head)
 3134 {
 3135         struct ice_fltr_mgmt_list_entry *fm_entry;
 3136         enum ice_status status = ICE_SUCCESS;
 3137 
 3138         /* check to make sure VSI ID is valid and within boundary */
 3139         if (!ice_is_vsi_valid(hw, vsi_handle))
 3140                 return ICE_ERR_PARAM;
 3141 
 3142         LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
 3143                             ice_fltr_mgmt_list_entry, list_entry) {
 3144                 if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
 3145                         continue;
 3146 
 3147                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
 3148                                                         vsi_list_head,
 3149                                                         &fm_entry->fltr_info);
 3150                 if (status)
 3151                         return status;
 3152         }
 3153         return status;
 3154 }
 3155 
 3156 /**
 3157  * ice_determine_promisc_mask
 3158  * @fi: filter info to parse
 3159  *
 3160  * Helper function to determine which ICE_PROMISC_ mask corresponds
 3161  * to given filter into.
 3162  */
 3163 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
 3164 {
 3165         u16 vid = fi->l_data.mac_vlan.vlan_id;
 3166         u8 *macaddr = fi->l_data.mac.mac_addr;
 3167         bool is_tx_fltr = false;
 3168         u8 promisc_mask = 0;
 3169 
 3170         if (fi->flag == ICE_FLTR_TX)
 3171                 is_tx_fltr = true;
 3172 
 3173         if (IS_BROADCAST_ETHER_ADDR(macaddr))
 3174                 promisc_mask |= is_tx_fltr ?
 3175                         ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
 3176         else if (IS_MULTICAST_ETHER_ADDR(macaddr))
 3177                 promisc_mask |= is_tx_fltr ?
 3178                         ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
 3179         else if (IS_UNICAST_ETHER_ADDR(macaddr))
 3180                 promisc_mask |= is_tx_fltr ?
 3181                         ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
 3182         if (vid)
 3183                 promisc_mask |= is_tx_fltr ?
 3184                         ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
 3185 
 3186         return promisc_mask;
 3187 }
 3188 
 3189 /**
 3190  * _ice_get_vsi_promisc - get promiscuous mode of given VSI
 3191  * @hw: pointer to the hardware structure
 3192  * @vsi_handle: VSI handle to retrieve info from
 3193  * @promisc_mask: pointer to mask to be filled in
 3194  * @vid: VLAN ID of promisc VLAN VSI
 3195  * @sw: pointer to switch info struct for which function add rule
 3196  * @lkup: switch rule filter lookup type
 3197  */
 3198 static enum ice_status
 3199 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
 3200                      u16 *vid, struct ice_switch_info *sw,
 3201                      enum ice_sw_lkup_type lkup)
 3202 {
 3203         struct ice_fltr_mgmt_list_entry *itr;
 3204         struct LIST_HEAD_TYPE *rule_head;
 3205         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
 3206 
 3207         if (!ice_is_vsi_valid(hw, vsi_handle) ||
 3208             (lkup != ICE_SW_LKUP_PROMISC && lkup != ICE_SW_LKUP_PROMISC_VLAN))
 3209                 return ICE_ERR_PARAM;
 3210 
 3211         *vid = 0;
 3212         *promisc_mask = 0;
 3213         rule_head = &sw->recp_list[lkup].filt_rules;
 3214         rule_lock = &sw->recp_list[lkup].filt_rule_lock;
 3215 
 3216         ice_acquire_lock(rule_lock);
 3217         LIST_FOR_EACH_ENTRY(itr, rule_head,
 3218                             ice_fltr_mgmt_list_entry, list_entry) {
 3219                 /* Continue if this filter doesn't apply to this VSI or the
 3220                  * VSI ID is not in the VSI map for this filter
 3221                  */
 3222                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
 3223                         continue;
 3224 
 3225                 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
 3226         }
 3227         ice_release_lock(rule_lock);
 3228 
 3229         return ICE_SUCCESS;
 3230 }
 3231 
 3232 /**
 3233  * ice_get_vsi_promisc - get promiscuous mode of given VSI
 3234  * @hw: pointer to the hardware structure
 3235  * @vsi_handle: VSI handle to retrieve info from
 3236  * @promisc_mask: pointer to mask to be filled in
 3237  * @vid: VLAN ID of promisc VLAN VSI
 3238  */
 3239 enum ice_status
 3240 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
 3241                     u16 *vid)
 3242 {
 3243         return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
 3244                                     vid, hw->switch_info, ICE_SW_LKUP_PROMISC);
 3245 }
 3246 
 3247 /**
 3248  * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
 3249  * @hw: pointer to the hardware structure
 3250  * @vsi_handle: VSI handle to retrieve info from
 3251  * @promisc_mask: pointer to mask to be filled in
 3252  * @vid: VLAN ID of promisc VLAN VSI
 3253  */
 3254 enum ice_status
 3255 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
 3256                          u16 *vid)
 3257 {
 3258         return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
 3259                                     vid, hw->switch_info,
 3260                                     ICE_SW_LKUP_PROMISC_VLAN);
 3261 }
 3262 
 3263 /**
 3264  * ice_remove_promisc - Remove promisc based filter rules
 3265  * @hw: pointer to the hardware structure
 3266  * @recp_id: recipe ID for which the rule needs to removed
 3267  * @v_list: list of promisc entries
 3268  */
 3269 static enum ice_status
 3270 ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
 3271                    struct LIST_HEAD_TYPE *v_list)
 3272 {
 3273         struct ice_fltr_list_entry *v_list_itr, *tmp;
 3274         struct ice_sw_recipe *recp_list;
 3275 
 3276         recp_list = &hw->switch_info->recp_list[recp_id];
 3277         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
 3278                                  list_entry) {
 3279                 v_list_itr->status =
 3280                         ice_remove_rule_internal(hw, recp_list, v_list_itr);
 3281                 if (v_list_itr->status)
 3282                         return v_list_itr->status;
 3283         }
 3284         return ICE_SUCCESS;
 3285 }
 3286 
 3287 /**
 3288  * _ice_clear_vsi_promisc - clear specified promiscuous mode(s)
 3289  * @hw: pointer to the hardware structure
 3290  * @vsi_handle: VSI handle to clear mode
 3291  * @promisc_mask: mask of promiscuous config bits to clear
 3292  * @vid: VLAN ID to clear VLAN promiscuous
 3293  * @sw: pointer to switch info struct for which function add rule
 3294  */
 3295 static enum ice_status
 3296 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 3297                        u16 vid, struct ice_switch_info *sw)
 3298 {
 3299         struct ice_fltr_list_entry *fm_entry, *tmp;
 3300         struct LIST_HEAD_TYPE remove_list_head;
 3301         struct ice_fltr_mgmt_list_entry *itr;
 3302         struct LIST_HEAD_TYPE *rule_head;
 3303         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
 3304         enum ice_status status = ICE_SUCCESS;
 3305         u8 recipe_id;
 3306 
 3307         if (!ice_is_vsi_valid(hw, vsi_handle))
 3308                 return ICE_ERR_PARAM;
 3309 
 3310         if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
 3311                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
 3312         else
 3313                 recipe_id = ICE_SW_LKUP_PROMISC;
 3314 
 3315         rule_head = &sw->recp_list[recipe_id].filt_rules;
 3316         rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
 3317 
 3318         INIT_LIST_HEAD(&remove_list_head);
 3319 
 3320         ice_acquire_lock(rule_lock);
 3321         LIST_FOR_EACH_ENTRY(itr, rule_head,
 3322                             ice_fltr_mgmt_list_entry, list_entry) {
 3323                 struct ice_fltr_info *fltr_info;
 3324                 u8 fltr_promisc_mask = 0;
 3325 
 3326                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
 3327                         continue;
 3328                 fltr_info = &itr->fltr_info;
 3329 
 3330                 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
 3331                     vid != fltr_info->l_data.mac_vlan.vlan_id)
 3332                         continue;
 3333 
 3334                 fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
 3335 
 3336                 /* Skip if filter is not completely specified by given mask */
 3337                 if (fltr_promisc_mask & ~promisc_mask)
 3338                         continue;
 3339 
 3340                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
 3341                                                         &remove_list_head,
 3342                                                         fltr_info);
 3343                 if (status) {
 3344                         ice_release_lock(rule_lock);
 3345                         goto free_fltr_list;
 3346                 }
 3347         }
 3348         ice_release_lock(rule_lock);
 3349 
 3350         status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
 3351 
 3352 free_fltr_list:
 3353         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
 3354                                  ice_fltr_list_entry, list_entry) {
 3355                 LIST_DEL(&fm_entry->list_entry);
 3356                 ice_free(hw, fm_entry);
 3357         }
 3358 
 3359         return status;
 3360 }
 3361 
 3362 /**
 3363  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
 3364  * @hw: pointer to the hardware structure
 3365  * @vsi_handle: VSI handle to clear mode
 3366  * @promisc_mask: mask of promiscuous config bits to clear
 3367  * @vid: VLAN ID to clear VLAN promiscuous
 3368  */
 3369 enum ice_status
 3370 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle,
 3371                       u8 promisc_mask, u16 vid)
 3372 {
 3373         return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask,
 3374                                       vid, hw->switch_info);
 3375 }
 3376 
 3377 /**
 3378  * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
 3379  * @hw: pointer to the hardware structure
 3380  * @vsi_handle: VSI handle to configure
 3381  * @promisc_mask: mask of promiscuous config bits
 3382  * @vid: VLAN ID to set VLAN promiscuous
 3383  * @lport: logical port number to configure promisc mode
 3384  * @sw: pointer to switch info struct for which function add rule
 3385  */
 3386 static enum ice_status
 3387 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 3388                      u16 vid, u8 lport, struct ice_switch_info *sw)
 3389 {
 3390         enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
 3391         struct ice_fltr_list_entry f_list_entry;
 3392         struct ice_fltr_info new_fltr;
 3393         enum ice_status status = ICE_SUCCESS;
 3394         bool is_tx_fltr;
 3395         u16 hw_vsi_id;
 3396         int pkt_type;
 3397         u8 recipe_id;
 3398 
 3399         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 3400 
 3401         if (!ice_is_vsi_valid(hw, vsi_handle))
 3402                 return ICE_ERR_PARAM;
 3403         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 3404 
 3405         ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM);
 3406 
 3407         if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
 3408                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
 3409                 new_fltr.l_data.mac_vlan.vlan_id = vid;
 3410                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
 3411         } else {
 3412                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
 3413                 recipe_id = ICE_SW_LKUP_PROMISC;
 3414         }
 3415 
 3416         /* Separate filters must be set for each direction/packet type
 3417          * combination, so we will loop over the mask value, store the
 3418          * individual type, and clear it out in the input mask as it
 3419          * is found.
 3420          */
 3421         while (promisc_mask) {
 3422                 struct ice_sw_recipe *recp_list;
 3423                 u8 *mac_addr;
 3424 
 3425                 pkt_type = 0;
 3426                 is_tx_fltr = false;
 3427 
 3428                 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
 3429                         promisc_mask &= ~ICE_PROMISC_UCAST_RX;
 3430                         pkt_type = UCAST_FLTR;
 3431                 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
 3432                         promisc_mask &= ~ICE_PROMISC_UCAST_TX;
 3433                         pkt_type = UCAST_FLTR;
 3434                         is_tx_fltr = true;
 3435                 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
 3436                         promisc_mask &= ~ICE_PROMISC_MCAST_RX;
 3437                         pkt_type = MCAST_FLTR;
 3438                 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
 3439                         promisc_mask &= ~ICE_PROMISC_MCAST_TX;
 3440                         pkt_type = MCAST_FLTR;
 3441                         is_tx_fltr = true;
 3442                 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
 3443                         promisc_mask &= ~ICE_PROMISC_BCAST_RX;
 3444                         pkt_type = BCAST_FLTR;
 3445                 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
 3446                         promisc_mask &= ~ICE_PROMISC_BCAST_TX;
 3447                         pkt_type = BCAST_FLTR;
 3448                         is_tx_fltr = true;
 3449                 }
 3450 
 3451                 /* Check for VLAN promiscuous flag */
 3452                 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
 3453                         promisc_mask &= ~ICE_PROMISC_VLAN_RX;
 3454                 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
 3455                         promisc_mask &= ~ICE_PROMISC_VLAN_TX;
 3456                         is_tx_fltr = true;
 3457                 }
 3458 
 3459                 /* Set filter DA based on packet type */
 3460                 mac_addr = new_fltr.l_data.mac.mac_addr;
 3461                 if (pkt_type == BCAST_FLTR) {
 3462                         ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM);
 3463                 } else if (pkt_type == MCAST_FLTR ||
 3464                            pkt_type == UCAST_FLTR) {
 3465                         /* Use the dummy ether header DA */
 3466                         ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN,
 3467                                    ICE_NONDMA_TO_NONDMA);
 3468                         if (pkt_type == MCAST_FLTR)
 3469                                 mac_addr[0] |= 0x1;     /* Set multicast bit */
 3470                 }
 3471 
 3472                 /* Need to reset this to zero for all iterations */
 3473                 new_fltr.flag = 0;
 3474                 if (is_tx_fltr) {
 3475                         new_fltr.flag |= ICE_FLTR_TX;
 3476                         new_fltr.src = hw_vsi_id;
 3477                 } else {
 3478                         new_fltr.flag |= ICE_FLTR_RX;
 3479                         new_fltr.src = lport;
 3480                 }
 3481 
 3482                 new_fltr.fltr_act = ICE_FWD_TO_VSI;
 3483                 new_fltr.vsi_handle = vsi_handle;
 3484                 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
 3485                 f_list_entry.fltr_info = new_fltr;
 3486                 recp_list = &sw->recp_list[recipe_id];
 3487 
 3488                 status = ice_add_rule_internal(hw, recp_list, lport,
 3489                                                &f_list_entry);
 3490                 if (status != ICE_SUCCESS)
 3491                         goto set_promisc_exit;
 3492         }
 3493 
 3494 set_promisc_exit:
 3495         return status;
 3496 }
 3497 
 3498 /**
 3499  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
 3500  * @hw: pointer to the hardware structure
 3501  * @vsi_handle: VSI handle to configure
 3502  * @promisc_mask: mask of promiscuous config bits
 3503  * @vid: VLAN ID to set VLAN promiscuous
 3504  */
 3505 enum ice_status
 3506 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 3507                     u16 vid)
 3508 {
 3509         return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid,
 3510                                     hw->port_info->lport,
 3511                                     hw->switch_info);
 3512 }
 3513 
 3514 /**
 3515  * _ice_set_vlan_vsi_promisc
 3516  * @hw: pointer to the hardware structure
 3517  * @vsi_handle: VSI handle to configure
 3518  * @promisc_mask: mask of promiscuous config bits
 3519  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
 3520  * @lport: logical port number to configure promisc mode
 3521  * @sw: pointer to switch info struct for which function add rule
 3522  *
 3523  * Configure VSI with all associated VLANs to given promiscuous mode(s)
 3524  */
 3525 static enum ice_status
 3526 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 3527                           bool rm_vlan_promisc, u8 lport,
 3528                           struct ice_switch_info *sw)
 3529 {
 3530         struct ice_fltr_list_entry *list_itr, *tmp;
 3531         struct LIST_HEAD_TYPE vsi_list_head;
 3532         struct LIST_HEAD_TYPE *vlan_head;
 3533         struct ice_lock *vlan_lock; /* Lock to protect filter rule list */
 3534         enum ice_status status;
 3535         u16 vlan_id;
 3536 
 3537         INIT_LIST_HEAD(&vsi_list_head);
 3538         vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
 3539         vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
 3540         ice_acquire_lock(vlan_lock);
 3541         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
 3542                                           &vsi_list_head);
 3543         ice_release_lock(vlan_lock);
 3544         if (status)
 3545                 goto free_fltr_list;
 3546 
 3547         LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry,
 3548                             list_entry) {
 3549                 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
 3550                 if (rm_vlan_promisc)
 3551                         status =  _ice_clear_vsi_promisc(hw, vsi_handle,
 3552                                                          promisc_mask,
 3553                                                          vlan_id, sw);
 3554                 else
 3555                         status =  _ice_set_vsi_promisc(hw, vsi_handle,
 3556                                                        promisc_mask, vlan_id,
 3557                                                        lport, sw);
 3558                 if (status)
 3559                         break;
 3560         }
 3561 
 3562 free_fltr_list:
 3563         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head,
 3564                                  ice_fltr_list_entry, list_entry) {
 3565                 LIST_DEL(&list_itr->list_entry);
 3566                 ice_free(hw, list_itr);
 3567         }
 3568         return status;
 3569 }
 3570 
 3571 /**
 3572  * ice_set_vlan_vsi_promisc
 3573  * @hw: pointer to the hardware structure
 3574  * @vsi_handle: VSI handle to configure
 3575  * @promisc_mask: mask of promiscuous config bits
 3576  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
 3577  *
 3578  * Configure VSI with all associated VLANs to given promiscuous mode(s)
 3579  */
 3580 enum ice_status
 3581 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
 3582                          bool rm_vlan_promisc)
 3583 {
 3584         return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask,
 3585                                          rm_vlan_promisc, hw->port_info->lport,
 3586                                          hw->switch_info);
 3587 }
 3588 
 3589 /**
 3590  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
 3591  * @hw: pointer to the hardware structure
 3592  * @vsi_handle: VSI handle to remove filters from
 3593  * @recp_list: recipe list from which function remove fltr
 3594  * @lkup: switch rule filter lookup type
 3595  */
 3596 static void
 3597 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
 3598                          struct ice_sw_recipe *recp_list,
 3599                          enum ice_sw_lkup_type lkup)
 3600 {
 3601         struct ice_fltr_list_entry *fm_entry;
 3602         struct LIST_HEAD_TYPE remove_list_head;
 3603         struct LIST_HEAD_TYPE *rule_head;
 3604         struct ice_fltr_list_entry *tmp;
 3605         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
 3606         enum ice_status status;
 3607 
 3608         INIT_LIST_HEAD(&remove_list_head);
 3609         rule_lock = &recp_list[lkup].filt_rule_lock;
 3610         rule_head = &recp_list[lkup].filt_rules;
 3611         ice_acquire_lock(rule_lock);
 3612         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
 3613                                           &remove_list_head);
 3614         ice_release_lock(rule_lock);
 3615         if (status)
 3616                 goto free_fltr_list;
 3617 
 3618         switch (lkup) {
 3619         case ICE_SW_LKUP_MAC:
 3620                 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]);
 3621                 break;
 3622         case ICE_SW_LKUP_VLAN:
 3623                 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]);
 3624                 break;
 3625         case ICE_SW_LKUP_PROMISC:
 3626         case ICE_SW_LKUP_PROMISC_VLAN:
 3627                 ice_remove_promisc(hw, lkup, &remove_list_head);
 3628                 break;
 3629         case ICE_SW_LKUP_MAC_VLAN:
 3630                 ice_debug(hw, ICE_DBG_SW, "MAC VLAN look up is not supported yet\n");
 3631                 break;
 3632         case ICE_SW_LKUP_ETHERTYPE:
 3633         case ICE_SW_LKUP_ETHERTYPE_MAC:
 3634                 ice_remove_eth_mac(hw, &remove_list_head);
 3635                 break;
 3636         case ICE_SW_LKUP_DFLT:
 3637                 ice_debug(hw, ICE_DBG_SW, "Remove filters for this lookup type hasn't been implemented yet\n");
 3638                 break;
 3639         case ICE_SW_LKUP_LAST:
 3640                 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n");
 3641                 break;
 3642         }
 3643 
 3644 free_fltr_list:
 3645         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
 3646                                  ice_fltr_list_entry, list_entry) {
 3647                 LIST_DEL(&fm_entry->list_entry);
 3648                 ice_free(hw, fm_entry);
 3649         }
 3650 }
 3651 
 3652 /**
 3653  * ice_remove_vsi_fltr_rule - Remove all filters for a VSI
 3654  * @hw: pointer to the hardware structure
 3655  * @vsi_handle: VSI handle to remove filters from
 3656  * @sw: pointer to switch info struct
 3657  */
 3658 static void
 3659 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle,
 3660                          struct ice_switch_info *sw)
 3661 {
 3662         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 3663 
 3664         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3665                                  sw->recp_list, ICE_SW_LKUP_MAC);
 3666         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3667                                  sw->recp_list, ICE_SW_LKUP_MAC_VLAN);
 3668         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3669                                  sw->recp_list, ICE_SW_LKUP_PROMISC);
 3670         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3671                                  sw->recp_list, ICE_SW_LKUP_VLAN);
 3672         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3673                                  sw->recp_list, ICE_SW_LKUP_DFLT);
 3674         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3675                                  sw->recp_list, ICE_SW_LKUP_ETHERTYPE);
 3676         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3677                                  sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC);
 3678         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
 3679                                  sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN);
 3680 }
 3681 
 3682 /**
 3683  * ice_remove_vsi_fltr - Remove all filters for a VSI
 3684  * @hw: pointer to the hardware structure
 3685  * @vsi_handle: VSI handle to remove filters from
 3686  */
 3687 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
 3688 {
 3689         ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info);
 3690 }
 3691 
 3692 /**
 3693  * ice_alloc_res_cntr - allocating resource counter
 3694  * @hw: pointer to the hardware structure
 3695  * @type: type of resource
 3696  * @alloc_shared: if set it is shared else dedicated
 3697  * @num_items: number of entries requested for FD resource type
 3698  * @counter_id: counter index returned by AQ call
 3699  */
 3700 static enum ice_status
 3701 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
 3702                    u16 *counter_id)
 3703 {
 3704         struct ice_aqc_alloc_free_res_elem *buf;
 3705         enum ice_status status;
 3706         u16 buf_len;
 3707 
 3708         /* Allocate resource */
 3709         buf_len = ice_struct_size(buf, elem, 1);
 3710         buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
 3711         if (!buf)
 3712                 return ICE_ERR_NO_MEMORY;
 3713 
 3714         buf->num_elems = CPU_TO_LE16(num_items);
 3715         buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
 3716                                       ICE_AQC_RES_TYPE_M) | alloc_shared);
 3717 
 3718         status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
 3719                                        ice_aqc_opc_alloc_res, NULL);
 3720         if (status)
 3721                 goto exit;
 3722 
 3723         *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp);
 3724 
 3725 exit:
 3726         ice_free(hw, buf);
 3727         return status;
 3728 }
 3729 
 3730 /**
 3731  * ice_free_res_cntr - free resource counter
 3732  * @hw: pointer to the hardware structure
 3733  * @type: type of resource
 3734  * @alloc_shared: if set it is shared else dedicated
 3735  * @num_items: number of entries to be freed for FD resource type
 3736  * @counter_id: counter ID resource which needs to be freed
 3737  */
 3738 static enum ice_status
 3739 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
 3740                   u16 counter_id)
 3741 {
 3742         struct ice_aqc_alloc_free_res_elem *buf;
 3743         enum ice_status status;
 3744         u16 buf_len;
 3745 
 3746         /* Free resource */
 3747         buf_len = ice_struct_size(buf, elem, 1);
 3748         buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
 3749         if (!buf)
 3750                 return ICE_ERR_NO_MEMORY;
 3751 
 3752         buf->num_elems = CPU_TO_LE16(num_items);
 3753         buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
 3754                                       ICE_AQC_RES_TYPE_M) | alloc_shared);
 3755         buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
 3756 
 3757         status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
 3758                                        ice_aqc_opc_free_res, NULL);
 3759         if (status)
 3760                 ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
 3761 
 3762         ice_free(hw, buf);
 3763         return status;
 3764 }
 3765 
 3766 /**
 3767  * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type
 3768  * @hw: pointer to the hardware structure
 3769  * @counter_id: returns counter index
 3770  */
 3771 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id)
 3772 {
 3773         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
 3774                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
 3775                                   counter_id);
 3776 }
 3777 
 3778 /**
 3779  * ice_free_vlan_res_counter - Free counter resource for VLAN type
 3780  * @hw: pointer to the hardware structure
 3781  * @counter_id: counter index to be freed
 3782  */
 3783 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id)
 3784 {
 3785         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
 3786                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
 3787                                  counter_id);
 3788 }
 3789 
 3790 /**
 3791  * ice_alloc_res_lg_act - add large action resource
 3792  * @hw: pointer to the hardware structure
 3793  * @l_id: large action ID to fill it in
 3794  * @num_acts: number of actions to hold with a large action entry
 3795  */
 3796 static enum ice_status
 3797 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts)
 3798 {
 3799         struct ice_aqc_alloc_free_res_elem *sw_buf;
 3800         enum ice_status status;
 3801         u16 buf_len;
 3802 
 3803         if (num_acts > ICE_MAX_LG_ACT || num_acts == 0)
 3804                 return ICE_ERR_PARAM;
 3805 
 3806         /* Allocate resource for large action */
 3807         buf_len = ice_struct_size(sw_buf, elem, 1);
 3808         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
 3809         if (!sw_buf)
 3810                 return ICE_ERR_NO_MEMORY;
 3811 
 3812         sw_buf->num_elems = CPU_TO_LE16(1);
 3813 
 3814         /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1.
 3815          * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3.
 3816          * If num_acts is greater than 2, then use
 3817          * ICE_AQC_RES_TYPE_WIDE_TABLE_4.
 3818          * The num_acts cannot exceed 4. This was ensured at the
 3819          * beginning of the function.
 3820          */
 3821         if (num_acts == 1)
 3822                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1);
 3823         else if (num_acts == 2)
 3824                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2);
 3825         else
 3826                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4);
 3827 
 3828         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
 3829                                        ice_aqc_opc_alloc_res, NULL);
 3830         if (!status)
 3831                 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
 3832 
 3833         ice_free(hw, sw_buf);
 3834         return status;
 3835 }
 3836 
 3837 /**
 3838  * ice_add_mac_with_sw_marker - add filter with sw marker
 3839  * @hw: pointer to the hardware structure
 3840  * @f_info: filter info structure containing the MAC filter information
 3841  * @sw_marker: sw marker to tag the Rx descriptor with
 3842  */
 3843 enum ice_status
 3844 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info,
 3845                            u16 sw_marker)
 3846 {
 3847         struct ice_fltr_mgmt_list_entry *m_entry;
 3848         struct ice_fltr_list_entry fl_info;
 3849         struct ice_sw_recipe *recp_list;
 3850         struct LIST_HEAD_TYPE l_head;
 3851         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
 3852         enum ice_status ret;
 3853         bool entry_exists;
 3854         u16 lg_act_id;
 3855 
 3856         if (f_info->fltr_act != ICE_FWD_TO_VSI)
 3857                 return ICE_ERR_PARAM;
 3858 
 3859         if (f_info->lkup_type != ICE_SW_LKUP_MAC)
 3860                 return ICE_ERR_PARAM;
 3861 
 3862         if (sw_marker == ICE_INVAL_SW_MARKER_ID)
 3863                 return ICE_ERR_PARAM;
 3864 
 3865         if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
 3866                 return ICE_ERR_PARAM;
 3867         f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
 3868 
 3869         /* Add filter if it doesn't exist so then the adding of large
 3870          * action always results in update
 3871          */
 3872 
 3873         INIT_LIST_HEAD(&l_head);
 3874         fl_info.fltr_info = *f_info;
 3875         LIST_ADD(&fl_info.list_entry, &l_head);
 3876 
 3877         entry_exists = false;
 3878         ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
 3879                                hw->port_info->lport);
 3880         if (ret == ICE_ERR_ALREADY_EXISTS)
 3881                 entry_exists = true;
 3882         else if (ret)
 3883                 return ret;
 3884 
 3885         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
 3886         rule_lock = &recp_list->filt_rule_lock;
 3887         ice_acquire_lock(rule_lock);
 3888         /* Get the book keeping entry for the filter */
 3889         m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
 3890         if (!m_entry)
 3891                 goto exit_error;
 3892 
 3893         /* If counter action was enabled for this rule then don't enable
 3894          * sw marker large action
 3895          */
 3896         if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
 3897                 ret = ICE_ERR_PARAM;
 3898                 goto exit_error;
 3899         }
 3900 
 3901         /* if same marker was added before */
 3902         if (m_entry->sw_marker_id == sw_marker) {
 3903                 ret = ICE_ERR_ALREADY_EXISTS;
 3904                 goto exit_error;
 3905         }
 3906 
 3907         /* Allocate a hardware table entry to hold large act. Three actions
 3908          * for marker based large action
 3909          */
 3910         ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3);
 3911         if (ret)
 3912                 goto exit_error;
 3913 
 3914         if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
 3915                 goto exit_error;
 3916 
 3917         /* Update the switch rule to add the marker action */
 3918         ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id);
 3919         if (!ret) {
 3920                 ice_release_lock(rule_lock);
 3921                 return ret;
 3922         }
 3923 
 3924 exit_error:
 3925         ice_release_lock(rule_lock);
 3926         /* only remove entry if it did not exist previously */
 3927         if (!entry_exists)
 3928                 ret = ice_remove_mac(hw, &l_head);
 3929 
 3930         return ret;
 3931 }
 3932 
 3933 /**
 3934  * ice_add_mac_with_counter - add filter with counter enabled
 3935  * @hw: pointer to the hardware structure
 3936  * @f_info: pointer to filter info structure containing the MAC filter
 3937  *          information
 3938  */
 3939 enum ice_status
 3940 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info)
 3941 {
 3942         struct ice_fltr_mgmt_list_entry *m_entry;
 3943         struct ice_fltr_list_entry fl_info;
 3944         struct ice_sw_recipe *recp_list;
 3945         struct LIST_HEAD_TYPE l_head;
 3946         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
 3947         enum ice_status ret;
 3948         bool entry_exist;
 3949         u16 counter_id;
 3950         u16 lg_act_id;
 3951 
 3952         if (f_info->fltr_act != ICE_FWD_TO_VSI)
 3953                 return ICE_ERR_PARAM;
 3954 
 3955         if (f_info->lkup_type != ICE_SW_LKUP_MAC)
 3956                 return ICE_ERR_PARAM;
 3957 
 3958         if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
 3959                 return ICE_ERR_PARAM;
 3960         f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
 3961         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
 3962 
 3963         entry_exist = false;
 3964 
 3965         rule_lock = &recp_list->filt_rule_lock;
 3966 
 3967         /* Add filter if it doesn't exist so then the adding of large
 3968          * action always results in update
 3969          */
 3970         INIT_LIST_HEAD(&l_head);
 3971 
 3972         fl_info.fltr_info = *f_info;
 3973         LIST_ADD(&fl_info.list_entry, &l_head);
 3974 
 3975         ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
 3976                                hw->port_info->lport);
 3977         if (ret == ICE_ERR_ALREADY_EXISTS)
 3978                 entry_exist = true;
 3979         else if (ret)
 3980                 return ret;
 3981 
 3982         ice_acquire_lock(rule_lock);
 3983         m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
 3984         if (!m_entry) {
 3985                 ret = ICE_ERR_BAD_PTR;
 3986                 goto exit_error;
 3987         }
 3988 
 3989         /* Don't enable counter for a filter for which sw marker was enabled */
 3990         if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) {
 3991                 ret = ICE_ERR_PARAM;
 3992                 goto exit_error;
 3993         }
 3994 
 3995         /* If a counter was already enabled then don't need to add again */
 3996         if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
 3997                 ret = ICE_ERR_ALREADY_EXISTS;
 3998                 goto exit_error;
 3999         }
 4000 
 4001         /* Allocate a hardware table entry to VLAN counter */
 4002         ret = ice_alloc_vlan_res_counter(hw, &counter_id);
 4003         if (ret)
 4004                 goto exit_error;
 4005 
 4006         /* Allocate a hardware table entry to hold large act. Two actions for
 4007          * counter based large action
 4008          */
 4009         ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2);
 4010         if (ret)
 4011                 goto exit_error;
 4012 
 4013         if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
 4014                 goto exit_error;
 4015 
 4016         /* Update the switch rule to add the counter action */
 4017         ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id);
 4018         if (!ret) {
 4019                 ice_release_lock(rule_lock);
 4020                 return ret;
 4021         }
 4022 
 4023 exit_error:
 4024         ice_release_lock(rule_lock);
 4025         /* only remove entry if it did not exist previously */
 4026         if (!entry_exist)
 4027                 ret = ice_remove_mac(hw, &l_head);
 4028 
 4029         return ret;
 4030 }
 4031 
 4032 /**
 4033  * ice_replay_fltr - Replay all the filters stored by a specific list head
 4034  * @hw: pointer to the hardware structure
 4035  * @list_head: list for which filters needs to be replayed
 4036  * @recp_id: Recipe ID for which rules need to be replayed
 4037  */
 4038 static enum ice_status
 4039 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head)
 4040 {
 4041         struct ice_fltr_mgmt_list_entry *itr;
 4042         enum ice_status status = ICE_SUCCESS;
 4043         struct ice_sw_recipe *recp_list;
 4044         u8 lport = hw->port_info->lport;
 4045         struct LIST_HEAD_TYPE l_head;
 4046 
 4047         if (LIST_EMPTY(list_head))
 4048                 return status;
 4049 
 4050         recp_list = &hw->switch_info->recp_list[recp_id];
 4051         /* Move entries from the given list_head to a temporary l_head so that
 4052          * they can be replayed. Otherwise when trying to re-add the same
 4053          * filter, the function will return already exists
 4054          */
 4055         LIST_REPLACE_INIT(list_head, &l_head);
 4056 
 4057         /* Mark the given list_head empty by reinitializing it so filters
 4058          * could be added again by *handler
 4059          */
 4060         LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry,
 4061                             list_entry) {
 4062                 struct ice_fltr_list_entry f_entry;
 4063                 u16 vsi_handle;
 4064 
 4065                 f_entry.fltr_info = itr->fltr_info;
 4066                 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) {
 4067                         status = ice_add_rule_internal(hw, recp_list, lport,
 4068                                                        &f_entry);
 4069                         if (status != ICE_SUCCESS)
 4070                                 goto end;
 4071                         continue;
 4072                 }
 4073 
 4074                 /* Add a filter per VSI separately */
 4075                 ice_for_each_set_bit(vsi_handle, itr->vsi_list_info->vsi_map,
 4076                                      ICE_MAX_VSI) {
 4077                         if (!ice_is_vsi_valid(hw, vsi_handle))
 4078                                 break;
 4079 
 4080                         ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
 4081                         f_entry.fltr_info.vsi_handle = vsi_handle;
 4082                         f_entry.fltr_info.fwd_id.hw_vsi_id =
 4083                                 ice_get_hw_vsi_num(hw, vsi_handle);
 4084                         f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
 4085                         if (recp_id == ICE_SW_LKUP_VLAN)
 4086                                 status = ice_add_vlan_internal(hw, recp_list,
 4087                                                                &f_entry);
 4088                         else
 4089                                 status = ice_add_rule_internal(hw, recp_list,
 4090                                                                lport,
 4091                                                                &f_entry);
 4092                         if (status != ICE_SUCCESS)
 4093                                 goto end;
 4094                 }
 4095         }
 4096 end:
 4097         /* Clear the filter management list */
 4098         ice_rem_sw_rule_info(hw, &l_head);
 4099         return status;
 4100 }
 4101 
 4102 /**
 4103  * ice_replay_all_fltr - replay all filters stored in bookkeeping lists
 4104  * @hw: pointer to the hardware structure
 4105  *
 4106  * NOTE: This function does not clean up partially added filters on error.
 4107  * It is up to caller of the function to issue a reset or fail early.
 4108  */
 4109 enum ice_status ice_replay_all_fltr(struct ice_hw *hw)
 4110 {
 4111         struct ice_switch_info *sw = hw->switch_info;
 4112         enum ice_status status = ICE_SUCCESS;
 4113         u8 i;
 4114 
 4115         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
 4116                 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules;
 4117 
 4118                 status = ice_replay_fltr(hw, i, head);
 4119                 if (status != ICE_SUCCESS)
 4120                         return status;
 4121         }
 4122         return status;
 4123 }
 4124 
 4125 /**
 4126  * ice_replay_vsi_fltr - Replay filters for requested VSI
 4127  * @hw: pointer to the hardware structure
 4128  * @pi: pointer to port information structure
 4129  * @sw: pointer to switch info struct for which function replays filters
 4130  * @vsi_handle: driver VSI handle
 4131  * @recp_id: Recipe ID for which rules need to be replayed
 4132  * @list_head: list for which filters need to be replayed
 4133  *
 4134  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
 4135  * It is required to pass valid VSI handle.
 4136  */
 4137 static enum ice_status
 4138 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi,
 4139                     struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id,
 4140                     struct LIST_HEAD_TYPE *list_head)
 4141 {
 4142         struct ice_fltr_mgmt_list_entry *itr;
 4143         enum ice_status status = ICE_SUCCESS;
 4144         struct ice_sw_recipe *recp_list;
 4145         u16 hw_vsi_id;
 4146 
 4147         if (LIST_EMPTY(list_head))
 4148                 return status;
 4149         recp_list = &sw->recp_list[recp_id];
 4150         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
 4151 
 4152         LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry,
 4153                             list_entry) {
 4154                 struct ice_fltr_list_entry f_entry;
 4155 
 4156                 f_entry.fltr_info = itr->fltr_info;
 4157                 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
 4158                     itr->fltr_info.vsi_handle == vsi_handle) {
 4159                         /* update the src in case it is VSI num */
 4160                         if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
 4161                                 f_entry.fltr_info.src = hw_vsi_id;
 4162                         status = ice_add_rule_internal(hw, recp_list,
 4163                                                        pi->lport,
 4164                                                        &f_entry);
 4165                         if (status != ICE_SUCCESS)
 4166                                 goto end;
 4167                         continue;
 4168                 }
 4169                 if (!itr->vsi_list_info ||
 4170                     !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle))
 4171                         continue;
 4172                 /* Clearing it so that the logic can add it back */
 4173                 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
 4174                 f_entry.fltr_info.vsi_handle = vsi_handle;
 4175                 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
 4176                 /* update the src in case it is VSI num */
 4177                 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
 4178                         f_entry.fltr_info.src = hw_vsi_id;
 4179                 if (recp_id == ICE_SW_LKUP_VLAN)
 4180                         status = ice_add_vlan_internal(hw, recp_list, &f_entry);
 4181                 else
 4182                         status = ice_add_rule_internal(hw, recp_list,
 4183                                                        pi->lport,
 4184                                                        &f_entry);
 4185                 if (status != ICE_SUCCESS)
 4186                         goto end;
 4187         }
 4188 end:
 4189         return status;
 4190 }
 4191 
 4192 /**
 4193  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
 4194  * @hw: pointer to the hardware structure
 4195  * @pi: pointer to port information structure
 4196  * @vsi_handle: driver VSI handle
 4197  *
 4198  * Replays filters for requested VSI via vsi_handle.
 4199  */
 4200 enum ice_status
 4201 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi,
 4202                         u16 vsi_handle)
 4203 {
 4204         struct ice_switch_info *sw = hw->switch_info;
 4205         enum ice_status status = ICE_SUCCESS;
 4206         u8 i;
 4207 
 4208         /* Update the recipes that were created */
 4209         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
 4210                 struct LIST_HEAD_TYPE *head;
 4211 
 4212                 head = &sw->recp_list[i].filt_replay_rules;
 4213                 if (!sw->recp_list[i].adv_rule)
 4214                         status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i,
 4215                                                      head);
 4216                 if (status != ICE_SUCCESS)
 4217                         return status;
 4218         }
 4219 
 4220         return ICE_SUCCESS;
 4221 }
 4222 
 4223 /**
 4224  * ice_rm_sw_replay_rule_info - helper function to delete filter replay rules
 4225  * @hw: pointer to the HW struct
 4226  * @sw: pointer to switch info struct for which function removes filters
 4227  *
 4228  * Deletes the filter replay rules for given switch
 4229  */
 4230 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw)
 4231 {
 4232         u8 i;
 4233 
 4234         if (!sw)
 4235                 return;
 4236 
 4237         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
 4238                 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) {
 4239                         struct LIST_HEAD_TYPE *l_head;
 4240 
 4241                         l_head = &sw->recp_list[i].filt_replay_rules;
 4242                         if (!sw->recp_list[i].adv_rule)
 4243                                 ice_rem_sw_rule_info(hw, l_head);
 4244                 }
 4245         }
 4246 }
 4247 
 4248 /**
 4249  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
 4250  * @hw: pointer to the HW struct
 4251  *
 4252  * Deletes the filter replay rules.
 4253  */
 4254 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
 4255 {
 4256         ice_rm_sw_replay_rule_info(hw, hw->switch_info);
 4257 }
 4258 

Cache object: 818729d75e580f2124bb9d362c65f843


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