linux/drivers/net/ethernet/intel/ice/ice_switch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2018, Intel Corporation. */
   3
   4#include "ice_lib.h"
   5#include "ice_switch.h"
   6
   7#define ICE_ETH_DA_OFFSET               0
   8#define ICE_ETH_ETHTYPE_OFFSET          12
   9#define ICE_ETH_VLAN_TCI_OFFSET         14
  10#define ICE_MAX_VLAN_ID                 0xFFF
  11
  12/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
  13 * struct to configure any switch filter rules.
  14 * {DA (6 bytes), SA(6 bytes),
  15 * Ether type (2 bytes for header without VLAN tag) OR
  16 * VLAN tag (4 bytes for header with VLAN tag) }
  17 *
  18 * Word on Hardcoded values
  19 * byte 0 = 0x2: to identify it as locally administered DA MAC
  20 * byte 6 = 0x2: to identify it as locally administered SA MAC
  21 * byte 12 = 0x81 & byte 13 = 0x00:
  22 *      In case of VLAN filter first two bytes defines ether type (0x8100)
  23 *      and remaining two bytes are placeholder for programming a given VLAN ID
  24 *      In case of Ether type filter it is treated as header without VLAN tag
  25 *      and byte 12 and 13 is used to program a given Ether type instead
  26 */
  27#define DUMMY_ETH_HDR_LEN               16
  28static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
  29                                                        0x2, 0, 0, 0, 0, 0,
  30                                                        0x81, 0, 0, 0};
  31
  32#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
  33        (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \
  34         (DUMMY_ETH_HDR_LEN * \
  35          sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))
  36#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
  37        (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
  38#define ICE_SW_RULE_LG_ACT_SIZE(n) \
  39        (offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \
  40         ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))
  41#define ICE_SW_RULE_VSI_LIST_SIZE(n) \
  42        (offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \
  43         ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))
  44
  45/**
  46 * ice_init_def_sw_recp - initialize the recipe book keeping tables
  47 * @hw: pointer to the HW struct
  48 *
  49 * Allocate memory for the entire recipe table and initialize the structures/
  50 * entries corresponding to basic recipes.
  51 */
  52enum ice_status ice_init_def_sw_recp(struct ice_hw *hw)
  53{
  54        struct ice_sw_recipe *recps;
  55        u8 i;
  56
  57        recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
  58                             sizeof(*recps), GFP_KERNEL);
  59        if (!recps)
  60                return ICE_ERR_NO_MEMORY;
  61
  62        for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
  63                recps[i].root_rid = i;
  64                INIT_LIST_HEAD(&recps[i].filt_rules);
  65                INIT_LIST_HEAD(&recps[i].filt_replay_rules);
  66                mutex_init(&recps[i].filt_rule_lock);
  67        }
  68
  69        hw->switch_info->recp_list = recps;
  70
  71        return 0;
  72}
  73
  74/**
  75 * ice_aq_get_sw_cfg - get switch configuration
  76 * @hw: pointer to the hardware structure
  77 * @buf: pointer to the result buffer
  78 * @buf_size: length of the buffer available for response
  79 * @req_desc: pointer to requested descriptor
  80 * @num_elems: pointer to number of elements
  81 * @cd: pointer to command details structure or NULL
  82 *
  83 * Get switch configuration (0x0200) to be placed in buf.
  84 * This admin command returns information such as initial VSI/port number
  85 * and switch ID it belongs to.
  86 *
  87 * NOTE: *req_desc is both an input/output parameter.
  88 * The caller of this function first calls this function with *request_desc set
  89 * to 0. If the response from f/w has *req_desc set to 0, all the switch
  90 * configuration information has been returned; if non-zero (meaning not all
  91 * the information was returned), the caller should call this function again
  92 * with *req_desc set to the previous value returned by f/w to get the
  93 * next block of switch configuration information.
  94 *
  95 * *num_elems is output only parameter. This reflects the number of elements
  96 * in response buffer. The caller of this function to use *num_elems while
  97 * parsing the response buffer.
  98 */
  99static enum ice_status
 100ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
 101                  u16 buf_size, u16 *req_desc, u16 *num_elems,
 102                  struct ice_sq_cd *cd)
 103{
 104        struct ice_aqc_get_sw_cfg *cmd;
 105        struct ice_aq_desc desc;
 106        enum ice_status status;
 107
 108        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
 109        cmd = &desc.params.get_sw_conf;
 110        cmd->element = cpu_to_le16(*req_desc);
 111
 112        status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
 113        if (!status) {
 114                *req_desc = le16_to_cpu(cmd->element);
 115                *num_elems = le16_to_cpu(cmd->num_elems);
 116        }
 117
 118        return status;
 119}
 120
 121/**
 122 * ice_aq_add_vsi
 123 * @hw: pointer to the HW struct
 124 * @vsi_ctx: pointer to a VSI context struct
 125 * @cd: pointer to command details structure or NULL
 126 *
 127 * Add a VSI context to the hardware (0x0210)
 128 */
 129static enum ice_status
 130ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
 131               struct ice_sq_cd *cd)
 132{
 133        struct ice_aqc_add_update_free_vsi_resp *res;
 134        struct ice_aqc_add_get_update_free_vsi *cmd;
 135        struct ice_aq_desc desc;
 136        enum ice_status status;
 137
 138        cmd = &desc.params.vsi_cmd;
 139        res = &desc.params.add_update_free_vsi_res;
 140
 141        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
 142
 143        if (!vsi_ctx->alloc_from_pool)
 144                cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
 145                                           ICE_AQ_VSI_IS_VALID);
 146        cmd->vf_id = vsi_ctx->vf_num;
 147
 148        cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
 149
 150        desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
 151
 152        status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
 153                                 sizeof(vsi_ctx->info), cd);
 154
 155        if (!status) {
 156                vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
 157                vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
 158                vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
 159        }
 160
 161        return status;
 162}
 163
 164/**
 165 * ice_aq_free_vsi
 166 * @hw: pointer to the HW struct
 167 * @vsi_ctx: pointer to a VSI context struct
 168 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
 169 * @cd: pointer to command details structure or NULL
 170 *
 171 * Free VSI context info from hardware (0x0213)
 172 */
 173static enum ice_status
 174ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
 175                bool keep_vsi_alloc, struct ice_sq_cd *cd)
 176{
 177        struct ice_aqc_add_update_free_vsi_resp *resp;
 178        struct ice_aqc_add_get_update_free_vsi *cmd;
 179        struct ice_aq_desc desc;
 180        enum ice_status status;
 181
 182        cmd = &desc.params.vsi_cmd;
 183        resp = &desc.params.add_update_free_vsi_res;
 184
 185        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
 186
 187        cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
 188        if (keep_vsi_alloc)
 189                cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
 190
 191        status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 192        if (!status) {
 193                vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
 194                vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
 195        }
 196
 197        return status;
 198}
 199
 200/**
 201 * ice_aq_update_vsi
 202 * @hw: pointer to the HW struct
 203 * @vsi_ctx: pointer to a VSI context struct
 204 * @cd: pointer to command details structure or NULL
 205 *
 206 * Update VSI context in the hardware (0x0211)
 207 */
 208static enum ice_status
 209ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
 210                  struct ice_sq_cd *cd)
 211{
 212        struct ice_aqc_add_update_free_vsi_resp *resp;
 213        struct ice_aqc_add_get_update_free_vsi *cmd;
 214        struct ice_aq_desc desc;
 215        enum ice_status status;
 216
 217        cmd = &desc.params.vsi_cmd;
 218        resp = &desc.params.add_update_free_vsi_res;
 219
 220        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
 221
 222        cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
 223
 224        desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
 225
 226        status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
 227                                 sizeof(vsi_ctx->info), cd);
 228
 229        if (!status) {
 230                vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
 231                vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
 232        }
 233
 234        return status;
 235}
 236
 237/**
 238 * ice_is_vsi_valid - check whether the VSI is valid or not
 239 * @hw: pointer to the HW struct
 240 * @vsi_handle: VSI handle
 241 *
 242 * check whether the VSI is valid or not
 243 */
 244bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
 245{
 246        return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
 247}
 248
 249/**
 250 * ice_get_hw_vsi_num - return the HW VSI number
 251 * @hw: pointer to the HW struct
 252 * @vsi_handle: VSI handle
 253 *
 254 * return the HW VSI number
 255 * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
 256 */
 257u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
 258{
 259        return hw->vsi_ctx[vsi_handle]->vsi_num;
 260}
 261
 262/**
 263 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
 264 * @hw: pointer to the HW struct
 265 * @vsi_handle: VSI handle
 266 *
 267 * return the VSI context entry for a given VSI handle
 268 */
 269struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
 270{
 271        return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
 272}
 273
 274/**
 275 * ice_save_vsi_ctx - save the VSI context for a given VSI handle
 276 * @hw: pointer to the HW struct
 277 * @vsi_handle: VSI handle
 278 * @vsi: VSI context pointer
 279 *
 280 * save the VSI context entry for a given VSI handle
 281 */
 282static void
 283ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
 284{
 285        hw->vsi_ctx[vsi_handle] = vsi;
 286}
 287
 288/**
 289 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
 290 * @hw: pointer to the HW struct
 291 * @vsi_handle: VSI handle
 292 */
 293static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
 294{
 295        struct ice_vsi_ctx *vsi;
 296        u8 i;
 297
 298        vsi = ice_get_vsi_ctx(hw, vsi_handle);
 299        if (!vsi)
 300                return;
 301        ice_for_each_traffic_class(i) {
 302                if (vsi->lan_q_ctx[i]) {
 303                        devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
 304                        vsi->lan_q_ctx[i] = NULL;
 305                }
 306                if (vsi->rdma_q_ctx[i]) {
 307                        devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
 308                        vsi->rdma_q_ctx[i] = NULL;
 309                }
 310        }
 311}
 312
 313/**
 314 * ice_clear_vsi_ctx - clear the VSI context entry
 315 * @hw: pointer to the HW struct
 316 * @vsi_handle: VSI handle
 317 *
 318 * clear the VSI context entry
 319 */
 320static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
 321{
 322        struct ice_vsi_ctx *vsi;
 323
 324        vsi = ice_get_vsi_ctx(hw, vsi_handle);
 325        if (vsi) {
 326                ice_clear_vsi_q_ctx(hw, vsi_handle);
 327                devm_kfree(ice_hw_to_dev(hw), vsi);
 328                hw->vsi_ctx[vsi_handle] = NULL;
 329        }
 330}
 331
 332/**
 333 * ice_clear_all_vsi_ctx - clear all the VSI context entries
 334 * @hw: pointer to the HW struct
 335 */
 336void ice_clear_all_vsi_ctx(struct ice_hw *hw)
 337{
 338        u16 i;
 339
 340        for (i = 0; i < ICE_MAX_VSI; i++)
 341                ice_clear_vsi_ctx(hw, i);
 342}
 343
 344/**
 345 * ice_add_vsi - add VSI context to the hardware and VSI handle list
 346 * @hw: pointer to the HW struct
 347 * @vsi_handle: unique VSI handle provided by drivers
 348 * @vsi_ctx: pointer to a VSI context struct
 349 * @cd: pointer to command details structure or NULL
 350 *
 351 * Add a VSI context to the hardware also add it into the VSI handle list.
 352 * If this function gets called after reset for existing VSIs then update
 353 * with the new HW VSI number in the corresponding VSI handle list entry.
 354 */
 355enum ice_status
 356ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 357            struct ice_sq_cd *cd)
 358{
 359        struct ice_vsi_ctx *tmp_vsi_ctx;
 360        enum ice_status status;
 361
 362        if (vsi_handle >= ICE_MAX_VSI)
 363                return ICE_ERR_PARAM;
 364        status = ice_aq_add_vsi(hw, vsi_ctx, cd);
 365        if (status)
 366                return status;
 367        tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
 368        if (!tmp_vsi_ctx) {
 369                /* Create a new VSI context */
 370                tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
 371                                           sizeof(*tmp_vsi_ctx), GFP_KERNEL);
 372                if (!tmp_vsi_ctx) {
 373                        ice_aq_free_vsi(hw, vsi_ctx, false, cd);
 374                        return ICE_ERR_NO_MEMORY;
 375                }
 376                *tmp_vsi_ctx = *vsi_ctx;
 377                ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
 378        } else {
 379                /* update with new HW VSI num */
 380                tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
 381        }
 382
 383        return 0;
 384}
 385
 386/**
 387 * ice_free_vsi- free VSI context from hardware and VSI handle list
 388 * @hw: pointer to the HW struct
 389 * @vsi_handle: unique VSI handle
 390 * @vsi_ctx: pointer to a VSI context struct
 391 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
 392 * @cd: pointer to command details structure or NULL
 393 *
 394 * Free VSI context info from hardware as well as from VSI handle list
 395 */
 396enum ice_status
 397ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 398             bool keep_vsi_alloc, struct ice_sq_cd *cd)
 399{
 400        enum ice_status status;
 401
 402        if (!ice_is_vsi_valid(hw, vsi_handle))
 403                return ICE_ERR_PARAM;
 404        vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
 405        status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
 406        if (!status)
 407                ice_clear_vsi_ctx(hw, vsi_handle);
 408        return status;
 409}
 410
 411/**
 412 * ice_update_vsi
 413 * @hw: pointer to the HW struct
 414 * @vsi_handle: unique VSI handle
 415 * @vsi_ctx: pointer to a VSI context struct
 416 * @cd: pointer to command details structure or NULL
 417 *
 418 * Update VSI context in the hardware
 419 */
 420enum ice_status
 421ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 422               struct ice_sq_cd *cd)
 423{
 424        if (!ice_is_vsi_valid(hw, vsi_handle))
 425                return ICE_ERR_PARAM;
 426        vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
 427        return ice_aq_update_vsi(hw, vsi_ctx, cd);
 428}
 429
 430/**
 431 * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI
 432 * @hw: pointer to HW struct
 433 * @vsi_handle: VSI SW index
 434 * @enable: boolean for enable/disable
 435 */
 436int
 437ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
 438{
 439        struct ice_vsi_ctx *ctx;
 440
 441        ctx = ice_get_vsi_ctx(hw, vsi_handle);
 442        if (!ctx)
 443                return -EIO;
 444
 445        if (enable)
 446                ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 447        else
 448                ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 449
 450        return ice_status_to_errno(ice_update_vsi(hw, vsi_handle, ctx, NULL));
 451}
 452
 453/**
 454 * ice_aq_alloc_free_vsi_list
 455 * @hw: pointer to the HW struct
 456 * @vsi_list_id: VSI list ID returned or used for lookup
 457 * @lkup_type: switch rule filter lookup type
 458 * @opc: switch rules population command type - pass in the command opcode
 459 *
 460 * allocates or free a VSI list resource
 461 */
 462static enum ice_status
 463ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
 464                           enum ice_sw_lkup_type lkup_type,
 465                           enum ice_adminq_opc opc)
 466{
 467        struct ice_aqc_alloc_free_res_elem *sw_buf;
 468        struct ice_aqc_res_elem *vsi_ele;
 469        enum ice_status status;
 470        u16 buf_len;
 471
 472        buf_len = struct_size(sw_buf, elem, 1);
 473        sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
 474        if (!sw_buf)
 475                return ICE_ERR_NO_MEMORY;
 476        sw_buf->num_elems = cpu_to_le16(1);
 477
 478        if (lkup_type == ICE_SW_LKUP_MAC ||
 479            lkup_type == ICE_SW_LKUP_MAC_VLAN ||
 480            lkup_type == ICE_SW_LKUP_ETHERTYPE ||
 481            lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
 482            lkup_type == ICE_SW_LKUP_PROMISC ||
 483            lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
 484                sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
 485        } else if (lkup_type == ICE_SW_LKUP_VLAN) {
 486                sw_buf->res_type =
 487                        cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
 488        } else {
 489                status = ICE_ERR_PARAM;
 490                goto ice_aq_alloc_free_vsi_list_exit;
 491        }
 492
 493        if (opc == ice_aqc_opc_free_res)
 494                sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
 495
 496        status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
 497        if (status)
 498                goto ice_aq_alloc_free_vsi_list_exit;
 499
 500        if (opc == ice_aqc_opc_alloc_res) {
 501                vsi_ele = &sw_buf->elem[0];
 502                *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
 503        }
 504
 505ice_aq_alloc_free_vsi_list_exit:
 506        devm_kfree(ice_hw_to_dev(hw), sw_buf);
 507        return status;
 508}
 509
 510/**
 511 * ice_aq_sw_rules - add/update/remove switch rules
 512 * @hw: pointer to the HW struct
 513 * @rule_list: pointer to switch rule population list
 514 * @rule_list_sz: total size of the rule list in bytes
 515 * @num_rules: number of switch rules in the rule_list
 516 * @opc: switch rules population command type - pass in the command opcode
 517 * @cd: pointer to command details structure or NULL
 518 *
 519 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
 520 */
 521static enum ice_status
 522ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
 523                u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
 524{
 525        struct ice_aq_desc desc;
 526        enum ice_status status;
 527
 528        if (opc != ice_aqc_opc_add_sw_rules &&
 529            opc != ice_aqc_opc_update_sw_rules &&
 530            opc != ice_aqc_opc_remove_sw_rules)
 531                return ICE_ERR_PARAM;
 532
 533        ice_fill_dflt_direct_cmd_desc(&desc, opc);
 534
 535        desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
 536        desc.params.sw_rules.num_rules_fltr_entry_index =
 537                cpu_to_le16(num_rules);
 538        status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
 539        if (opc != ice_aqc_opc_add_sw_rules &&
 540            hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
 541                status = ICE_ERR_DOES_NOT_EXIST;
 542
 543        return status;
 544}
 545
 546/* ice_init_port_info - Initialize port_info with switch configuration data
 547 * @pi: pointer to port_info
 548 * @vsi_port_num: VSI number or port number
 549 * @type: Type of switch element (port or VSI)
 550 * @swid: switch ID of the switch the element is attached to
 551 * @pf_vf_num: PF or VF number
 552 * @is_vf: true if the element is a VF, false otherwise
 553 */
 554static void
 555ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
 556                   u16 swid, u16 pf_vf_num, bool is_vf)
 557{
 558        switch (type) {
 559        case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
 560                pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
 561                pi->sw_id = swid;
 562                pi->pf_vf_num = pf_vf_num;
 563                pi->is_vf = is_vf;
 564                pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
 565                pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
 566                break;
 567        default:
 568                ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
 569                break;
 570        }
 571}
 572
 573/* ice_get_initial_sw_cfg - Get initial port and default VSI data
 574 * @hw: pointer to the hardware structure
 575 */
 576enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
 577{
 578        struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
 579        enum ice_status status;
 580        u16 req_desc = 0;
 581        u16 num_elems;
 582        u16 i;
 583
 584        rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
 585                            GFP_KERNEL);
 586
 587        if (!rbuf)
 588                return ICE_ERR_NO_MEMORY;
 589
 590        /* Multiple calls to ice_aq_get_sw_cfg may be required
 591         * to get all the switch configuration information. The need
 592         * for additional calls is indicated by ice_aq_get_sw_cfg
 593         * writing a non-zero value in req_desc
 594         */
 595        do {
 596                struct ice_aqc_get_sw_cfg_resp_elem *ele;
 597
 598                status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
 599                                           &req_desc, &num_elems, NULL);
 600
 601                if (status)
 602                        break;
 603
 604                for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
 605                        u16 pf_vf_num, swid, vsi_port_num;
 606                        bool is_vf = false;
 607                        u8 res_type;
 608
 609                        vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
 610                                ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
 611
 612                        pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
 613                                ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
 614
 615                        swid = le16_to_cpu(ele->swid);
 616
 617                        if (le16_to_cpu(ele->pf_vf_num) &
 618                            ICE_AQC_GET_SW_CONF_RESP_IS_VF)
 619                                is_vf = true;
 620
 621                        res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
 622                                        ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
 623
 624                        if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
 625                                /* FW VSI is not needed. Just continue. */
 626                                continue;
 627                        }
 628
 629                        ice_init_port_info(hw->port_info, vsi_port_num,
 630                                           res_type, swid, pf_vf_num, is_vf);
 631                }
 632        } while (req_desc && !status);
 633
 634        devm_kfree(ice_hw_to_dev(hw), rbuf);
 635        return status;
 636}
 637
 638/**
 639 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
 640 * @hw: pointer to the hardware structure
 641 * @fi: filter info structure to fill/update
 642 *
 643 * This helper function populates the lb_en and lan_en elements of the provided
 644 * ice_fltr_info struct using the switch's type and characteristics of the
 645 * switch rule being configured.
 646 */
 647static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
 648{
 649        fi->lb_en = false;
 650        fi->lan_en = false;
 651        if ((fi->flag & ICE_FLTR_TX) &&
 652            (fi->fltr_act == ICE_FWD_TO_VSI ||
 653             fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
 654             fi->fltr_act == ICE_FWD_TO_Q ||
 655             fi->fltr_act == ICE_FWD_TO_QGRP)) {
 656                /* Setting LB for prune actions will result in replicated
 657                 * packets to the internal switch that will be dropped.
 658                 */
 659                if (fi->lkup_type != ICE_SW_LKUP_VLAN)
 660                        fi->lb_en = true;
 661
 662                /* Set lan_en to TRUE if
 663                 * 1. The switch is a VEB AND
 664                 * 2
 665                 * 2.1 The lookup is a directional lookup like ethertype,
 666                 * promiscuous, ethertype-MAC, promiscuous-VLAN
 667                 * and default-port OR
 668                 * 2.2 The lookup is VLAN, OR
 669                 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
 670                 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
 671                 *
 672                 * OR
 673                 *
 674                 * The switch is a VEPA.
 675                 *
 676                 * In all other cases, the LAN enable has to be set to false.
 677                 */
 678                if (hw->evb_veb) {
 679                        if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
 680                            fi->lkup_type == ICE_SW_LKUP_PROMISC ||
 681                            fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
 682                            fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
 683                            fi->lkup_type == ICE_SW_LKUP_DFLT ||
 684                            fi->lkup_type == ICE_SW_LKUP_VLAN ||
 685                            (fi->lkup_type == ICE_SW_LKUP_MAC &&
 686                             !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
 687                            (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
 688                             !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
 689                                fi->lan_en = true;
 690                } else {
 691                        fi->lan_en = true;
 692                }
 693        }
 694}
 695
 696/**
 697 * ice_fill_sw_rule - Helper function to fill switch rule structure
 698 * @hw: pointer to the hardware structure
 699 * @f_info: entry containing packet forwarding information
 700 * @s_rule: switch rule structure to be filled in based on mac_entry
 701 * @opc: switch rules population command type - pass in the command opcode
 702 */
 703static void
 704ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
 705                 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
 706{
 707        u16 vlan_id = ICE_MAX_VLAN_ID + 1;
 708        void *daddr = NULL;
 709        u16 eth_hdr_sz;
 710        u8 *eth_hdr;
 711        u32 act = 0;
 712        __be16 *off;
 713        u8 q_rgn;
 714
 715        if (opc == ice_aqc_opc_remove_sw_rules) {
 716                s_rule->pdata.lkup_tx_rx.act = 0;
 717                s_rule->pdata.lkup_tx_rx.index =
 718                        cpu_to_le16(f_info->fltr_rule_id);
 719                s_rule->pdata.lkup_tx_rx.hdr_len = 0;
 720                return;
 721        }
 722
 723        eth_hdr_sz = sizeof(dummy_eth_header);
 724        eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
 725
 726        /* initialize the ether header with a dummy header */
 727        memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
 728        ice_fill_sw_info(hw, f_info);
 729
 730        switch (f_info->fltr_act) {
 731        case ICE_FWD_TO_VSI:
 732                act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
 733                        ICE_SINGLE_ACT_VSI_ID_M;
 734                if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
 735                        act |= ICE_SINGLE_ACT_VSI_FORWARDING |
 736                                ICE_SINGLE_ACT_VALID_BIT;
 737                break;
 738        case ICE_FWD_TO_VSI_LIST:
 739                act |= ICE_SINGLE_ACT_VSI_LIST;
 740                act |= (f_info->fwd_id.vsi_list_id <<
 741                        ICE_SINGLE_ACT_VSI_LIST_ID_S) &
 742                        ICE_SINGLE_ACT_VSI_LIST_ID_M;
 743                if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
 744                        act |= ICE_SINGLE_ACT_VSI_FORWARDING |
 745                                ICE_SINGLE_ACT_VALID_BIT;
 746                break;
 747        case ICE_FWD_TO_Q:
 748                act |= ICE_SINGLE_ACT_TO_Q;
 749                act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
 750                        ICE_SINGLE_ACT_Q_INDEX_M;
 751                break;
 752        case ICE_DROP_PACKET:
 753                act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
 754                        ICE_SINGLE_ACT_VALID_BIT;
 755                break;
 756        case ICE_FWD_TO_QGRP:
 757                q_rgn = f_info->qgrp_size > 0 ?
 758                        (u8)ilog2(f_info->qgrp_size) : 0;
 759                act |= ICE_SINGLE_ACT_TO_Q;
 760                act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
 761                        ICE_SINGLE_ACT_Q_INDEX_M;
 762                act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
 763                        ICE_SINGLE_ACT_Q_REGION_M;
 764                break;
 765        default:
 766                return;
 767        }
 768
 769        if (f_info->lb_en)
 770                act |= ICE_SINGLE_ACT_LB_ENABLE;
 771        if (f_info->lan_en)
 772                act |= ICE_SINGLE_ACT_LAN_ENABLE;
 773
 774        switch (f_info->lkup_type) {
 775        case ICE_SW_LKUP_MAC:
 776                daddr = f_info->l_data.mac.mac_addr;
 777                break;
 778        case ICE_SW_LKUP_VLAN:
 779                vlan_id = f_info->l_data.vlan.vlan_id;
 780                if (f_info->fltr_act == ICE_FWD_TO_VSI ||
 781                    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
 782                        act |= ICE_SINGLE_ACT_PRUNE;
 783                        act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
 784                }
 785                break;
 786        case ICE_SW_LKUP_ETHERTYPE_MAC:
 787                daddr = f_info->l_data.ethertype_mac.mac_addr;
 788                fallthrough;
 789        case ICE_SW_LKUP_ETHERTYPE:
 790                off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
 791                *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
 792                break;
 793        case ICE_SW_LKUP_MAC_VLAN:
 794                daddr = f_info->l_data.mac_vlan.mac_addr;
 795                vlan_id = f_info->l_data.mac_vlan.vlan_id;
 796                break;
 797        case ICE_SW_LKUP_PROMISC_VLAN:
 798                vlan_id = f_info->l_data.mac_vlan.vlan_id;
 799                fallthrough;
 800        case ICE_SW_LKUP_PROMISC:
 801                daddr = f_info->l_data.mac_vlan.mac_addr;
 802                break;
 803        default:
 804                break;
 805        }
 806
 807        s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
 808                cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
 809                cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
 810
 811        /* Recipe set depending on lookup type */
 812        s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(f_info->lkup_type);
 813        s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(f_info->src);
 814        s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
 815
 816        if (daddr)
 817                ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
 818
 819        if (!(vlan_id > ICE_MAX_VLAN_ID)) {
 820                off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
 821                *off = cpu_to_be16(vlan_id);
 822        }
 823
 824        /* Create the switch rule with the final dummy Ethernet header */
 825        if (opc != ice_aqc_opc_update_sw_rules)
 826                s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(eth_hdr_sz);
 827}
 828
 829/**
 830 * ice_add_marker_act
 831 * @hw: pointer to the hardware structure
 832 * @m_ent: the management entry for which sw marker needs to be added
 833 * @sw_marker: sw marker to tag the Rx descriptor with
 834 * @l_id: large action resource ID
 835 *
 836 * Create a large action to hold software marker and update the switch rule
 837 * entry pointed by m_ent with newly created large action
 838 */
 839static enum ice_status
 840ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
 841                   u16 sw_marker, u16 l_id)
 842{
 843        struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
 844        /* For software marker we need 3 large actions
 845         * 1. FWD action: FWD TO VSI or VSI LIST
 846         * 2. GENERIC VALUE action to hold the profile ID
 847         * 3. GENERIC VALUE action to hold the software marker ID
 848         */
 849        const u16 num_lg_acts = 3;
 850        enum ice_status status;
 851        u16 lg_act_size;
 852        u16 rules_size;
 853        u32 act;
 854        u16 id;
 855
 856        if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
 857                return ICE_ERR_PARAM;
 858
 859        /* Create two back-to-back switch rules and submit them to the HW using
 860         * one memory buffer:
 861         *    1. Large Action
 862         *    2. Look up Tx Rx
 863         */
 864        lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
 865        rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
 866        lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
 867        if (!lg_act)
 868                return ICE_ERR_NO_MEMORY;
 869
 870        rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
 871
 872        /* Fill in the first switch rule i.e. large action */
 873        lg_act->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
 874        lg_act->pdata.lg_act.index = cpu_to_le16(l_id);
 875        lg_act->pdata.lg_act.size = cpu_to_le16(num_lg_acts);
 876
 877        /* First action VSI forwarding or VSI list forwarding depending on how
 878         * many VSIs
 879         */
 880        id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
 881                m_ent->fltr_info.fwd_id.hw_vsi_id;
 882
 883        act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
 884        act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
 885        if (m_ent->vsi_count > 1)
 886                act |= ICE_LG_ACT_VSI_LIST;
 887        lg_act->pdata.lg_act.act[0] = cpu_to_le32(act);
 888
 889        /* Second action descriptor type */
 890        act = ICE_LG_ACT_GENERIC;
 891
 892        act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
 893        lg_act->pdata.lg_act.act[1] = cpu_to_le32(act);
 894
 895        act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
 896               ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
 897
 898        /* Third action Marker value */
 899        act |= ICE_LG_ACT_GENERIC;
 900        act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
 901                ICE_LG_ACT_GENERIC_VALUE_M;
 902
 903        lg_act->pdata.lg_act.act[2] = cpu_to_le32(act);
 904
 905        /* call the fill switch rule to fill the lookup Tx Rx structure */
 906        ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
 907                         ice_aqc_opc_update_sw_rules);
 908
 909        /* Update the action to point to the large action ID */
 910        rx_tx->pdata.lkup_tx_rx.act =
 911                cpu_to_le32(ICE_SINGLE_ACT_PTR |
 912                            ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
 913                             ICE_SINGLE_ACT_PTR_VAL_M));
 914
 915        /* Use the filter rule ID of the previously created rule with single
 916         * act. Once the update happens, hardware will treat this as large
 917         * action
 918         */
 919        rx_tx->pdata.lkup_tx_rx.index =
 920                cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
 921
 922        status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
 923                                 ice_aqc_opc_update_sw_rules, NULL);
 924        if (!status) {
 925                m_ent->lg_act_idx = l_id;
 926                m_ent->sw_marker_id = sw_marker;
 927        }
 928
 929        devm_kfree(ice_hw_to_dev(hw), lg_act);
 930        return status;
 931}
 932
 933/**
 934 * ice_create_vsi_list_map
 935 * @hw: pointer to the hardware structure
 936 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
 937 * @num_vsi: number of VSI handles in the array
 938 * @vsi_list_id: VSI list ID generated as part of allocate resource
 939 *
 940 * Helper function to create a new entry of VSI list ID to VSI mapping
 941 * using the given VSI list ID
 942 */
 943static struct ice_vsi_list_map_info *
 944ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
 945                        u16 vsi_list_id)
 946{
 947        struct ice_switch_info *sw = hw->switch_info;
 948        struct ice_vsi_list_map_info *v_map;
 949        int i;
 950
 951        v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL);
 952        if (!v_map)
 953                return NULL;
 954
 955        v_map->vsi_list_id = vsi_list_id;
 956        v_map->ref_cnt = 1;
 957        for (i = 0; i < num_vsi; i++)
 958                set_bit(vsi_handle_arr[i], v_map->vsi_map);
 959
 960        list_add(&v_map->list_entry, &sw->vsi_list_map_head);
 961        return v_map;
 962}
 963
 964/**
 965 * ice_update_vsi_list_rule
 966 * @hw: pointer to the hardware structure
 967 * @vsi_handle_arr: array of VSI handles to form a VSI list
 968 * @num_vsi: number of VSI handles in the array
 969 * @vsi_list_id: VSI list ID generated as part of allocate resource
 970 * @remove: Boolean value to indicate if this is a remove action
 971 * @opc: switch rules population command type - pass in the command opcode
 972 * @lkup_type: lookup type of the filter
 973 *
 974 * Call AQ command to add a new switch rule or update existing switch rule
 975 * using the given VSI list ID
 976 */
 977static enum ice_status
 978ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
 979                         u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
 980                         enum ice_sw_lkup_type lkup_type)
 981{
 982        struct ice_aqc_sw_rules_elem *s_rule;
 983        enum ice_status status;
 984        u16 s_rule_size;
 985        u16 rule_type;
 986        int i;
 987
 988        if (!num_vsi)
 989                return ICE_ERR_PARAM;
 990
 991        if (lkup_type == ICE_SW_LKUP_MAC ||
 992            lkup_type == ICE_SW_LKUP_MAC_VLAN ||
 993            lkup_type == ICE_SW_LKUP_ETHERTYPE ||
 994            lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
 995            lkup_type == ICE_SW_LKUP_PROMISC ||
 996            lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
 997                rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
 998                        ICE_AQC_SW_RULES_T_VSI_LIST_SET;
 999        else if (lkup_type == ICE_SW_LKUP_VLAN)
1000                rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
1001                        ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
1002        else
1003                return ICE_ERR_PARAM;
1004
1005        s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
1006        s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
1007        if (!s_rule)
1008                return ICE_ERR_NO_MEMORY;
1009        for (i = 0; i < num_vsi; i++) {
1010                if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
1011                        status = ICE_ERR_PARAM;
1012                        goto exit;
1013                }
1014                /* AQ call requires hw_vsi_id(s) */
1015                s_rule->pdata.vsi_list.vsi[i] =
1016                        cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
1017        }
1018
1019        s_rule->type = cpu_to_le16(rule_type);
1020        s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi);
1021        s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
1022
1023        status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
1024
1025exit:
1026        devm_kfree(ice_hw_to_dev(hw), s_rule);
1027        return status;
1028}
1029
1030/**
1031 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
1032 * @hw: pointer to the HW struct
1033 * @vsi_handle_arr: array of VSI handles to form a VSI list
1034 * @num_vsi: number of VSI handles in the array
1035 * @vsi_list_id: stores the ID of the VSI list to be created
1036 * @lkup_type: switch rule filter's lookup type
1037 */
1038static enum ice_status
1039ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1040                         u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
1041{
1042        enum ice_status status;
1043
1044        status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
1045                                            ice_aqc_opc_alloc_res);
1046        if (status)
1047                return status;
1048
1049        /* Update the newly created VSI list to include the specified VSIs */
1050        return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
1051                                        *vsi_list_id, false,
1052                                        ice_aqc_opc_add_sw_rules, lkup_type);
1053}
1054
1055/**
1056 * ice_create_pkt_fwd_rule
1057 * @hw: pointer to the hardware structure
1058 * @f_entry: entry containing packet forwarding information
1059 *
1060 * Create switch rule with given filter information and add an entry
1061 * to the corresponding filter management list to track this switch rule
1062 * and VSI mapping
1063 */
1064static enum ice_status
1065ice_create_pkt_fwd_rule(struct ice_hw *hw,
1066                        struct ice_fltr_list_entry *f_entry)
1067{
1068        struct ice_fltr_mgmt_list_entry *fm_entry;
1069        struct ice_aqc_sw_rules_elem *s_rule;
1070        enum ice_sw_lkup_type l_type;
1071        struct ice_sw_recipe *recp;
1072        enum ice_status status;
1073
1074        s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1075                              ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
1076        if (!s_rule)
1077                return ICE_ERR_NO_MEMORY;
1078        fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
1079                                GFP_KERNEL);
1080        if (!fm_entry) {
1081                status = ICE_ERR_NO_MEMORY;
1082                goto ice_create_pkt_fwd_rule_exit;
1083        }
1084
1085        fm_entry->fltr_info = f_entry->fltr_info;
1086
1087        /* Initialize all the fields for the management entry */
1088        fm_entry->vsi_count = 1;
1089        fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
1090        fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
1091        fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
1092
1093        ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
1094                         ice_aqc_opc_add_sw_rules);
1095
1096        status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1097                                 ice_aqc_opc_add_sw_rules, NULL);
1098        if (status) {
1099                devm_kfree(ice_hw_to_dev(hw), fm_entry);
1100                goto ice_create_pkt_fwd_rule_exit;
1101        }
1102
1103        f_entry->fltr_info.fltr_rule_id =
1104                le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
1105        fm_entry->fltr_info.fltr_rule_id =
1106                le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
1107
1108        /* The book keeping entries will get removed when base driver
1109         * calls remove filter AQ command
1110         */
1111        l_type = fm_entry->fltr_info.lkup_type;
1112        recp = &hw->switch_info->recp_list[l_type];
1113        list_add(&fm_entry->list_entry, &recp->filt_rules);
1114
1115ice_create_pkt_fwd_rule_exit:
1116        devm_kfree(ice_hw_to_dev(hw), s_rule);
1117        return status;
1118}
1119
1120/**
1121 * ice_update_pkt_fwd_rule
1122 * @hw: pointer to the hardware structure
1123 * @f_info: filter information for switch rule
1124 *
1125 * Call AQ command to update a previously created switch rule with a
1126 * VSI list ID
1127 */
1128static enum ice_status
1129ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
1130{
1131        struct ice_aqc_sw_rules_elem *s_rule;
1132        enum ice_status status;
1133
1134        s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1135                              ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
1136        if (!s_rule)
1137                return ICE_ERR_NO_MEMORY;
1138
1139        ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
1140
1141        s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(f_info->fltr_rule_id);
1142
1143        /* Update switch rule with new rule set to forward VSI list */
1144        status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1145                                 ice_aqc_opc_update_sw_rules, NULL);
1146
1147        devm_kfree(ice_hw_to_dev(hw), s_rule);
1148        return status;
1149}
1150
1151/**
1152 * ice_update_sw_rule_bridge_mode
1153 * @hw: pointer to the HW struct
1154 *
1155 * Updates unicast switch filter rules based on VEB/VEPA mode
1156 */
1157enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
1158{
1159        struct ice_switch_info *sw = hw->switch_info;
1160        struct ice_fltr_mgmt_list_entry *fm_entry;
1161        enum ice_status status = 0;
1162        struct list_head *rule_head;
1163        struct mutex *rule_lock; /* Lock to protect filter rule list */
1164
1165        rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1166        rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1167
1168        mutex_lock(rule_lock);
1169        list_for_each_entry(fm_entry, rule_head, list_entry) {
1170                struct ice_fltr_info *fi = &fm_entry->fltr_info;
1171                u8 *addr = fi->l_data.mac.mac_addr;
1172
1173                /* Update unicast Tx rules to reflect the selected
1174                 * VEB/VEPA mode
1175                 */
1176                if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
1177                    (fi->fltr_act == ICE_FWD_TO_VSI ||
1178                     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1179                     fi->fltr_act == ICE_FWD_TO_Q ||
1180                     fi->fltr_act == ICE_FWD_TO_QGRP)) {
1181                        status = ice_update_pkt_fwd_rule(hw, fi);
1182                        if (status)
1183                                break;
1184                }
1185        }
1186
1187        mutex_unlock(rule_lock);
1188
1189        return status;
1190}
1191
1192/**
1193 * ice_add_update_vsi_list
1194 * @hw: pointer to the hardware structure
1195 * @m_entry: pointer to current filter management list entry
1196 * @cur_fltr: filter information from the book keeping entry
1197 * @new_fltr: filter information with the new VSI to be added
1198 *
1199 * Call AQ command to add or update previously created VSI list with new VSI.
1200 *
1201 * Helper function to do book keeping associated with adding filter information
1202 * The algorithm to do the book keeping is described below :
1203 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
1204 *      if only one VSI has been added till now
1205 *              Allocate a new VSI list and add two VSIs
1206 *              to this list using switch rule command
1207 *              Update the previously created switch rule with the
1208 *              newly created VSI list ID
1209 *      if a VSI list was previously created
1210 *              Add the new VSI to the previously created VSI list set
1211 *              using the update switch rule command
1212 */
1213static enum ice_status
1214ice_add_update_vsi_list(struct ice_hw *hw,
1215                        struct ice_fltr_mgmt_list_entry *m_entry,
1216                        struct ice_fltr_info *cur_fltr,
1217                        struct ice_fltr_info *new_fltr)
1218{
1219        enum ice_status status = 0;
1220        u16 vsi_list_id = 0;
1221
1222        if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
1223             cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
1224                return ICE_ERR_NOT_IMPL;
1225
1226        if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
1227             new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
1228            (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
1229             cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
1230                return ICE_ERR_NOT_IMPL;
1231
1232        if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
1233                /* Only one entry existed in the mapping and it was not already
1234                 * a part of a VSI list. So, create a VSI list with the old and
1235                 * new VSIs.
1236                 */
1237                struct ice_fltr_info tmp_fltr;
1238                u16 vsi_handle_arr[2];
1239
1240                /* A rule already exists with the new VSI being added */
1241                if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
1242                        return ICE_ERR_ALREADY_EXISTS;
1243
1244                vsi_handle_arr[0] = cur_fltr->vsi_handle;
1245                vsi_handle_arr[1] = new_fltr->vsi_handle;
1246                status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1247                                                  &vsi_list_id,
1248                                                  new_fltr->lkup_type);
1249                if (status)
1250                        return status;
1251
1252                tmp_fltr = *new_fltr;
1253                tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
1254                tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1255                tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1256                /* Update the previous switch rule of "MAC forward to VSI" to
1257                 * "MAC fwd to VSI list"
1258                 */
1259                status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1260                if (status)
1261                        return status;
1262
1263                cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
1264                cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1265                m_entry->vsi_list_info =
1266                        ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1267                                                vsi_list_id);
1268
1269                if (!m_entry->vsi_list_info)
1270                        return ICE_ERR_NO_MEMORY;
1271
1272                /* If this entry was large action then the large action needs
1273                 * to be updated to point to FWD to VSI list
1274                 */
1275                if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
1276                        status =
1277                            ice_add_marker_act(hw, m_entry,
1278                                               m_entry->sw_marker_id,
1279                                               m_entry->lg_act_idx);
1280        } else {
1281                u16 vsi_handle = new_fltr->vsi_handle;
1282                enum ice_adminq_opc opcode;
1283
1284                if (!m_entry->vsi_list_info)
1285                        return ICE_ERR_CFG;
1286
1287                /* A rule already exists with the new VSI being added */
1288                if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
1289                        return 0;
1290
1291                /* Update the previously created VSI list set with
1292                 * the new VSI ID passed in
1293                 */
1294                vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
1295                opcode = ice_aqc_opc_update_sw_rules;
1296
1297                status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
1298                                                  vsi_list_id, false, opcode,
1299                                                  new_fltr->lkup_type);
1300                /* update VSI list mapping info with new VSI ID */
1301                if (!status)
1302                        set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
1303        }
1304        if (!status)
1305                m_entry->vsi_count++;
1306        return status;
1307}
1308
1309/**
1310 * ice_find_rule_entry - Search a rule entry
1311 * @hw: pointer to the hardware structure
1312 * @recp_id: lookup type for which the specified rule needs to be searched
1313 * @f_info: rule information
1314 *
1315 * Helper function to search for a given rule entry
1316 * Returns pointer to entry storing the rule if found
1317 */
1318static struct ice_fltr_mgmt_list_entry *
1319ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
1320{
1321        struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
1322        struct ice_switch_info *sw = hw->switch_info;
1323        struct list_head *list_head;
1324
1325        list_head = &sw->recp_list[recp_id].filt_rules;
1326        list_for_each_entry(list_itr, list_head, list_entry) {
1327                if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
1328                            sizeof(f_info->l_data)) &&
1329                    f_info->flag == list_itr->fltr_info.flag) {
1330                        ret = list_itr;
1331                        break;
1332                }
1333        }
1334        return ret;
1335}
1336
1337/**
1338 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
1339 * @hw: pointer to the hardware structure
1340 * @recp_id: lookup type for which VSI lists needs to be searched
1341 * @vsi_handle: VSI handle to be found in VSI list
1342 * @vsi_list_id: VSI list ID found containing vsi_handle
1343 *
1344 * Helper function to search a VSI list with single entry containing given VSI
1345 * handle element. This can be extended further to search VSI list with more
1346 * than 1 vsi_count. Returns pointer to VSI list entry if found.
1347 */
1348static struct ice_vsi_list_map_info *
1349ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
1350                        u16 *vsi_list_id)
1351{
1352        struct ice_vsi_list_map_info *map_info = NULL;
1353        struct ice_switch_info *sw = hw->switch_info;
1354        struct ice_fltr_mgmt_list_entry *list_itr;
1355        struct list_head *list_head;
1356
1357        list_head = &sw->recp_list[recp_id].filt_rules;
1358        list_for_each_entry(list_itr, list_head, list_entry) {
1359                if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
1360                        map_info = list_itr->vsi_list_info;
1361                        if (test_bit(vsi_handle, map_info->vsi_map)) {
1362                                *vsi_list_id = map_info->vsi_list_id;
1363                                return map_info;
1364                        }
1365                }
1366        }
1367        return NULL;
1368}
1369
1370/**
1371 * ice_add_rule_internal - add rule for a given lookup type
1372 * @hw: pointer to the hardware structure
1373 * @recp_id: lookup type (recipe ID) for which rule has to be added
1374 * @f_entry: structure containing MAC forwarding information
1375 *
1376 * Adds or updates the rule lists for a given recipe
1377 */
1378static enum ice_status
1379ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
1380                      struct ice_fltr_list_entry *f_entry)
1381{
1382        struct ice_switch_info *sw = hw->switch_info;
1383        struct ice_fltr_info *new_fltr, *cur_fltr;
1384        struct ice_fltr_mgmt_list_entry *m_entry;
1385        struct mutex *rule_lock; /* Lock to protect filter rule list */
1386        enum ice_status status = 0;
1387
1388        if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1389                return ICE_ERR_PARAM;
1390        f_entry->fltr_info.fwd_id.hw_vsi_id =
1391                ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1392
1393        rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1394
1395        mutex_lock(rule_lock);
1396        new_fltr = &f_entry->fltr_info;
1397        if (new_fltr->flag & ICE_FLTR_RX)
1398                new_fltr->src = hw->port_info->lport;
1399        else if (new_fltr->flag & ICE_FLTR_TX)
1400                new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
1401
1402        m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
1403        if (!m_entry) {
1404                mutex_unlock(rule_lock);
1405                return ice_create_pkt_fwd_rule(hw, f_entry);
1406        }
1407
1408        cur_fltr = &m_entry->fltr_info;
1409        status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
1410        mutex_unlock(rule_lock);
1411
1412        return status;
1413}
1414
1415/**
1416 * ice_remove_vsi_list_rule
1417 * @hw: pointer to the hardware structure
1418 * @vsi_list_id: VSI list ID generated as part of allocate resource
1419 * @lkup_type: switch rule filter lookup type
1420 *
1421 * The VSI list should be emptied before this function is called to remove the
1422 * VSI list.
1423 */
1424static enum ice_status
1425ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
1426                         enum ice_sw_lkup_type lkup_type)
1427{
1428        struct ice_aqc_sw_rules_elem *s_rule;
1429        enum ice_status status;
1430        u16 s_rule_size;
1431
1432        s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0);
1433        s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
1434        if (!s_rule)
1435                return ICE_ERR_NO_MEMORY;
1436
1437        s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
1438        s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
1439
1440        /* Free the vsi_list resource that we allocated. It is assumed that the
1441         * list is empty at this point.
1442         */
1443        status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1444                                            ice_aqc_opc_free_res);
1445
1446        devm_kfree(ice_hw_to_dev(hw), s_rule);
1447        return status;
1448}
1449
1450/**
1451 * ice_rem_update_vsi_list
1452 * @hw: pointer to the hardware structure
1453 * @vsi_handle: VSI handle of the VSI to remove
1454 * @fm_list: filter management entry for which the VSI list management needs to
1455 *           be done
1456 */
1457static enum ice_status
1458ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
1459                        struct ice_fltr_mgmt_list_entry *fm_list)
1460{
1461        enum ice_sw_lkup_type lkup_type;
1462        enum ice_status status = 0;
1463        u16 vsi_list_id;
1464
1465        if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
1466            fm_list->vsi_count == 0)
1467                return ICE_ERR_PARAM;
1468
1469        /* A rule with the VSI being removed does not exist */
1470        if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
1471                return ICE_ERR_DOES_NOT_EXIST;
1472
1473        lkup_type = fm_list->fltr_info.lkup_type;
1474        vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
1475        status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
1476                                          ice_aqc_opc_update_sw_rules,
1477                                          lkup_type);
1478        if (status)
1479                return status;
1480
1481        fm_list->vsi_count--;
1482        clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
1483
1484        if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
1485                struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
1486                struct ice_vsi_list_map_info *vsi_list_info =
1487                        fm_list->vsi_list_info;
1488                u16 rem_vsi_handle;
1489
1490                rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
1491                                                ICE_MAX_VSI);
1492                if (!ice_is_vsi_valid(hw, rem_vsi_handle))
1493                        return ICE_ERR_OUT_OF_RANGE;
1494
1495                /* Make sure VSI list is empty before removing it below */
1496                status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
1497                                                  vsi_list_id, true,
1498                                                  ice_aqc_opc_update_sw_rules,
1499                                                  lkup_type);
1500                if (status)
1501                        return status;
1502
1503                tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
1504                tmp_fltr_info.fwd_id.hw_vsi_id =
1505                        ice_get_hw_vsi_num(hw, rem_vsi_handle);
1506                tmp_fltr_info.vsi_handle = rem_vsi_handle;
1507                status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
1508                if (status) {
1509                        ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
1510                                  tmp_fltr_info.fwd_id.hw_vsi_id, status);
1511                        return status;
1512                }
1513
1514                fm_list->fltr_info = tmp_fltr_info;
1515        }
1516
1517        if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
1518            (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
1519                struct ice_vsi_list_map_info *vsi_list_info =
1520                        fm_list->vsi_list_info;
1521
1522                /* Remove the VSI list since it is no longer used */
1523                status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1524                if (status) {
1525                        ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
1526                                  vsi_list_id, status);
1527                        return status;
1528                }
1529
1530                list_del(&vsi_list_info->list_entry);
1531                devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
1532                fm_list->vsi_list_info = NULL;
1533        }
1534
1535        return status;
1536}
1537
1538/**
1539 * ice_remove_rule_internal - Remove a filter rule of a given type
1540 * @hw: pointer to the hardware structure
1541 * @recp_id: recipe ID for which the rule needs to removed
1542 * @f_entry: rule entry containing filter information
1543 */
1544static enum ice_status
1545ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
1546                         struct ice_fltr_list_entry *f_entry)
1547{
1548        struct ice_switch_info *sw = hw->switch_info;
1549        struct ice_fltr_mgmt_list_entry *list_elem;
1550        struct mutex *rule_lock; /* Lock to protect filter rule list */
1551        enum ice_status status = 0;
1552        bool remove_rule = false;
1553        u16 vsi_handle;
1554
1555        if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1556                return ICE_ERR_PARAM;
1557        f_entry->fltr_info.fwd_id.hw_vsi_id =
1558                ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1559
1560        rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1561        mutex_lock(rule_lock);
1562        list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
1563        if (!list_elem) {
1564                status = ICE_ERR_DOES_NOT_EXIST;
1565                goto exit;
1566        }
1567
1568        if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
1569                remove_rule = true;
1570        } else if (!list_elem->vsi_list_info) {
1571                status = ICE_ERR_DOES_NOT_EXIST;
1572                goto exit;
1573        } else if (list_elem->vsi_list_info->ref_cnt > 1) {
1574                /* a ref_cnt > 1 indicates that the vsi_list is being
1575                 * shared by multiple rules. Decrement the ref_cnt and
1576                 * remove this rule, but do not modify the list, as it
1577                 * is in-use by other rules.
1578                 */
1579                list_elem->vsi_list_info->ref_cnt--;
1580                remove_rule = true;
1581        } else {
1582                /* a ref_cnt of 1 indicates the vsi_list is only used
1583                 * by one rule. However, the original removal request is only
1584                 * for a single VSI. Update the vsi_list first, and only
1585                 * remove the rule if there are no further VSIs in this list.
1586                 */
1587                vsi_handle = f_entry->fltr_info.vsi_handle;
1588                status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
1589                if (status)
1590                        goto exit;
1591                /* if VSI count goes to zero after updating the VSI list */
1592                if (list_elem->vsi_count == 0)
1593                        remove_rule = true;
1594        }
1595
1596        if (remove_rule) {
1597                /* Remove the lookup rule */
1598                struct ice_aqc_sw_rules_elem *s_rule;
1599
1600                s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1601                                      ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
1602                                      GFP_KERNEL);
1603                if (!s_rule) {
1604                        status = ICE_ERR_NO_MEMORY;
1605                        goto exit;
1606                }
1607
1608                ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
1609                                 ice_aqc_opc_remove_sw_rules);
1610
1611                status = ice_aq_sw_rules(hw, s_rule,
1612                                         ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
1613                                         ice_aqc_opc_remove_sw_rules, NULL);
1614
1615                /* Remove a book keeping from the list */
1616                devm_kfree(ice_hw_to_dev(hw), s_rule);
1617
1618                if (status)
1619                        goto exit;
1620
1621                list_del(&list_elem->list_entry);
1622                devm_kfree(ice_hw_to_dev(hw), list_elem);
1623        }
1624exit:
1625        mutex_unlock(rule_lock);
1626        return status;
1627}
1628
1629/**
1630 * ice_add_mac - Add a MAC address based filter rule
1631 * @hw: pointer to the hardware structure
1632 * @m_list: list of MAC addresses and forwarding information
1633 *
1634 * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1635 * multiple unicast addresses, the function assumes that all the
1636 * addresses are unique in a given add_mac call. It doesn't
1637 * check for duplicates in this case, removing duplicates from a given
1638 * list should be taken care of in the caller of this function.
1639 */
1640enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
1641{
1642        struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1643        struct ice_fltr_list_entry *m_list_itr;
1644        struct list_head *rule_head;
1645        u16 total_elem_left, s_rule_size;
1646        struct ice_switch_info *sw;
1647        struct mutex *rule_lock; /* Lock to protect filter rule list */
1648        enum ice_status status = 0;
1649        u16 num_unicast = 0;
1650        u8 elem_sent;
1651
1652        if (!m_list || !hw)
1653                return ICE_ERR_PARAM;
1654
1655        s_rule = NULL;
1656        sw = hw->switch_info;
1657        rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1658        list_for_each_entry(m_list_itr, m_list, list_entry) {
1659                u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1660                u16 vsi_handle;
1661                u16 hw_vsi_id;
1662
1663                m_list_itr->fltr_info.flag = ICE_FLTR_TX;
1664                vsi_handle = m_list_itr->fltr_info.vsi_handle;
1665                if (!ice_is_vsi_valid(hw, vsi_handle))
1666                        return ICE_ERR_PARAM;
1667                hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
1668                m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
1669                /* update the src in case it is VSI num */
1670                if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
1671                        return ICE_ERR_PARAM;
1672                m_list_itr->fltr_info.src = hw_vsi_id;
1673                if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
1674                    is_zero_ether_addr(add))
1675                        return ICE_ERR_PARAM;
1676                if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
1677                        /* Don't overwrite the unicast address */
1678                        mutex_lock(rule_lock);
1679                        if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
1680                                                &m_list_itr->fltr_info)) {
1681                                mutex_unlock(rule_lock);
1682                                return ICE_ERR_ALREADY_EXISTS;
1683                        }
1684                        mutex_unlock(rule_lock);
1685                        num_unicast++;
1686                } else if (is_multicast_ether_addr(add) ||
1687                           (is_unicast_ether_addr(add) && hw->ucast_shared)) {
1688                        m_list_itr->status =
1689                                ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
1690                                                      m_list_itr);
1691                        if (m_list_itr->status)
1692                                return m_list_itr->status;
1693                }
1694        }
1695
1696        mutex_lock(rule_lock);
1697        /* Exit if no suitable entries were found for adding bulk switch rule */
1698        if (!num_unicast) {
1699                status = 0;
1700                goto ice_add_mac_exit;
1701        }
1702
1703        rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1704
1705        /* Allocate switch rule buffer for the bulk update for unicast */
1706        s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1707        s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
1708                              GFP_KERNEL);
1709        if (!s_rule) {
1710                status = ICE_ERR_NO_MEMORY;
1711                goto ice_add_mac_exit;
1712        }
1713
1714        r_iter = s_rule;
1715        list_for_each_entry(m_list_itr, m_list, list_entry) {
1716                struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1717                u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1718
1719                if (is_unicast_ether_addr(mac_addr)) {
1720                        ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
1721                                         ice_aqc_opc_add_sw_rules);
1722                        r_iter = (struct ice_aqc_sw_rules_elem *)
1723                                ((u8 *)r_iter + s_rule_size);
1724                }
1725        }
1726
1727        /* Call AQ bulk switch rule update for all unicast addresses */
1728        r_iter = s_rule;
1729        /* Call AQ switch rule in AQ_MAX chunk */
1730        for (total_elem_left = num_unicast; total_elem_left > 0;
1731             total_elem_left -= elem_sent) {
1732                struct ice_aqc_sw_rules_elem *entry = r_iter;
1733
1734                elem_sent = min_t(u8, total_elem_left,
1735                                  (ICE_AQ_MAX_BUF_LEN / s_rule_size));
1736                status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1737                                         elem_sent, ice_aqc_opc_add_sw_rules,
1738                                         NULL);
1739                if (status)
1740                        goto ice_add_mac_exit;
1741                r_iter = (struct ice_aqc_sw_rules_elem *)
1742                        ((u8 *)r_iter + (elem_sent * s_rule_size));
1743        }
1744
1745        /* Fill up rule ID based on the value returned from FW */
1746        r_iter = s_rule;
1747        list_for_each_entry(m_list_itr, m_list, list_entry) {
1748                struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1749                u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1750                struct ice_fltr_mgmt_list_entry *fm_entry;
1751
1752                if (is_unicast_ether_addr(mac_addr)) {
1753                        f_info->fltr_rule_id =
1754                                le16_to_cpu(r_iter->pdata.lkup_tx_rx.index);
1755                        f_info->fltr_act = ICE_FWD_TO_VSI;
1756                        /* Create an entry to track this MAC address */
1757                        fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
1758                                                sizeof(*fm_entry), GFP_KERNEL);
1759                        if (!fm_entry) {
1760                                status = ICE_ERR_NO_MEMORY;
1761                                goto ice_add_mac_exit;
1762                        }
1763                        fm_entry->fltr_info = *f_info;
1764                        fm_entry->vsi_count = 1;
1765                        /* The book keeping entries will get removed when
1766                         * base driver calls remove filter AQ command
1767                         */
1768
1769                        list_add(&fm_entry->list_entry, rule_head);
1770                        r_iter = (struct ice_aqc_sw_rules_elem *)
1771                                ((u8 *)r_iter + s_rule_size);
1772                }
1773        }
1774
1775ice_add_mac_exit:
1776        mutex_unlock(rule_lock);
1777        if (s_rule)
1778                devm_kfree(ice_hw_to_dev(hw), s_rule);
1779        return status;
1780}
1781
1782/**
1783 * ice_add_vlan_internal - Add one VLAN based filter rule
1784 * @hw: pointer to the hardware structure
1785 * @f_entry: filter entry containing one VLAN information
1786 */
1787static enum ice_status
1788ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1789{
1790        struct ice_switch_info *sw = hw->switch_info;
1791        struct ice_fltr_mgmt_list_entry *v_list_itr;
1792        struct ice_fltr_info *new_fltr, *cur_fltr;
1793        enum ice_sw_lkup_type lkup_type;
1794        u16 vsi_list_id = 0, vsi_handle;
1795        struct mutex *rule_lock; /* Lock to protect filter rule list */
1796        enum ice_status status = 0;
1797
1798        if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1799                return ICE_ERR_PARAM;
1800
1801        f_entry->fltr_info.fwd_id.hw_vsi_id =
1802                ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1803        new_fltr = &f_entry->fltr_info;
1804
1805        /* VLAN ID should only be 12 bits */
1806        if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
1807                return ICE_ERR_PARAM;
1808
1809        if (new_fltr->src_id != ICE_SRC_ID_VSI)
1810                return ICE_ERR_PARAM;
1811
1812        new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
1813        lkup_type = new_fltr->lkup_type;
1814        vsi_handle = new_fltr->vsi_handle;
1815        rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
1816        mutex_lock(rule_lock);
1817        v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
1818        if (!v_list_itr) {
1819                struct ice_vsi_list_map_info *map_info = NULL;
1820
1821                if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
1822                        /* All VLAN pruning rules use a VSI list. Check if
1823                         * there is already a VSI list containing VSI that we
1824                         * want to add. If found, use the same vsi_list_id for
1825                         * this new VLAN rule or else create a new list.
1826                         */
1827                        map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
1828                                                           vsi_handle,
1829                                                           &vsi_list_id);
1830                        if (!map_info) {
1831                                status = ice_create_vsi_list_rule(hw,
1832                                                                  &vsi_handle,
1833                                                                  1,
1834                                                                  &vsi_list_id,
1835                                                                  lkup_type);
1836                                if (status)
1837                                        goto exit;
1838                        }
1839                        /* Convert the action to forwarding to a VSI list. */
1840                        new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1841                        new_fltr->fwd_id.vsi_list_id = vsi_list_id;
1842                }
1843
1844                status = ice_create_pkt_fwd_rule(hw, f_entry);
1845                if (!status) {
1846                        v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
1847                                                         new_fltr);
1848                        if (!v_list_itr) {
1849                                status = ICE_ERR_DOES_NOT_EXIST;
1850                                goto exit;
1851                        }
1852                        /* reuse VSI list for new rule and increment ref_cnt */
1853                        if (map_info) {
1854                                v_list_itr->vsi_list_info = map_info;
1855                                map_info->ref_cnt++;
1856                        } else {
1857                                v_list_itr->vsi_list_info =
1858                                        ice_create_vsi_list_map(hw, &vsi_handle,
1859                                                                1, vsi_list_id);
1860                        }
1861                }
1862        } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
1863                /* Update existing VSI list to add new VSI ID only if it used
1864                 * by one VLAN rule.
1865                 */
1866                cur_fltr = &v_list_itr->fltr_info;
1867                status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
1868                                                 new_fltr);
1869        } else {
1870                /* If VLAN rule exists and VSI list being used by this rule is
1871                 * referenced by more than 1 VLAN rule. Then create a new VSI
1872                 * list appending previous VSI with new VSI and update existing
1873                 * VLAN rule to point to new VSI list ID
1874                 */
1875                struct ice_fltr_info tmp_fltr;
1876                u16 vsi_handle_arr[2];
1877                u16 cur_handle;
1878
1879                /* Current implementation only supports reusing VSI list with
1880                 * one VSI count. We should never hit below condition
1881                 */
1882                if (v_list_itr->vsi_count > 1 &&
1883                    v_list_itr->vsi_list_info->ref_cnt > 1) {
1884                        ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
1885                        status = ICE_ERR_CFG;
1886                        goto exit;
1887                }
1888
1889                cur_handle =
1890                        find_first_bit(v_list_itr->vsi_list_info->vsi_map,
1891                                       ICE_MAX_VSI);
1892
1893                /* A rule already exists with the new VSI being added */
1894                if (cur_handle == vsi_handle) {
1895                        status = ICE_ERR_ALREADY_EXISTS;
1896                        goto exit;
1897                }
1898
1899                vsi_handle_arr[0] = cur_handle;
1900                vsi_handle_arr[1] = vsi_handle;
1901                status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1902                                                  &vsi_list_id, lkup_type);
1903                if (status)
1904                        goto exit;
1905
1906                tmp_fltr = v_list_itr->fltr_info;
1907                tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
1908                tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1909                tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1910                /* Update the previous switch rule to a new VSI list which
1911                 * includes current VSI that is requested
1912                 */
1913                status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1914                if (status)
1915                        goto exit;
1916
1917                /* before overriding VSI list map info. decrement ref_cnt of
1918                 * previous VSI list
1919                 */
1920                v_list_itr->vsi_list_info->ref_cnt--;
1921
1922                /* now update to newly created list */
1923                v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
1924                v_list_itr->vsi_list_info =
1925                        ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1926                                                vsi_list_id);
1927                v_list_itr->vsi_count++;
1928        }
1929
1930exit:
1931        mutex_unlock(rule_lock);
1932        return status;
1933}
1934
1935/**
1936 * ice_add_vlan - Add VLAN based filter rule
1937 * @hw: pointer to the hardware structure
1938 * @v_list: list of VLAN entries and forwarding information
1939 */
1940enum ice_status ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
1941{
1942        struct ice_fltr_list_entry *v_list_itr;
1943
1944        if (!v_list || !hw)
1945                return ICE_ERR_PARAM;
1946
1947        list_for_each_entry(v_list_itr, v_list, list_entry) {
1948                if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
1949                        return ICE_ERR_PARAM;
1950                v_list_itr->fltr_info.flag = ICE_FLTR_TX;
1951                v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
1952                if (v_list_itr->status)
1953                        return v_list_itr->status;
1954        }
1955        return 0;
1956}
1957
1958/**
1959 * ice_add_eth_mac - Add ethertype and MAC based filter rule
1960 * @hw: pointer to the hardware structure
1961 * @em_list: list of ether type MAC filter, MAC is optional
1962 *
1963 * This function requires the caller to populate the entries in
1964 * the filter list with the necessary fields (including flags to
1965 * indicate Tx or Rx rules).
1966 */
1967enum ice_status
1968ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
1969{
1970        struct ice_fltr_list_entry *em_list_itr;
1971
1972        if (!em_list || !hw)
1973                return ICE_ERR_PARAM;
1974
1975        list_for_each_entry(em_list_itr, em_list, list_entry) {
1976                enum ice_sw_lkup_type l_type =
1977                        em_list_itr->fltr_info.lkup_type;
1978
1979                if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
1980                    l_type != ICE_SW_LKUP_ETHERTYPE)
1981                        return ICE_ERR_PARAM;
1982
1983                em_list_itr->status = ice_add_rule_internal(hw, l_type,
1984                                                            em_list_itr);
1985                if (em_list_itr->status)
1986                        return em_list_itr->status;
1987        }
1988        return 0;
1989}
1990
1991/**
1992 * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
1993 * @hw: pointer to the hardware structure
1994 * @em_list: list of ethertype or ethertype MAC entries
1995 */
1996enum ice_status
1997ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
1998{
1999        struct ice_fltr_list_entry *em_list_itr, *tmp;
2000
2001        if (!em_list || !hw)
2002                return ICE_ERR_PARAM;
2003
2004        list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
2005                enum ice_sw_lkup_type l_type =
2006                        em_list_itr->fltr_info.lkup_type;
2007
2008                if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
2009                    l_type != ICE_SW_LKUP_ETHERTYPE)
2010                        return ICE_ERR_PARAM;
2011
2012                em_list_itr->status = ice_remove_rule_internal(hw, l_type,
2013                                                               em_list_itr);
2014                if (em_list_itr->status)
2015                        return em_list_itr->status;
2016        }
2017        return 0;
2018}
2019
2020/**
2021 * ice_rem_sw_rule_info
2022 * @hw: pointer to the hardware structure
2023 * @rule_head: pointer to the switch list structure that we want to delete
2024 */
2025static void
2026ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
2027{
2028        if (!list_empty(rule_head)) {
2029                struct ice_fltr_mgmt_list_entry *entry;
2030                struct ice_fltr_mgmt_list_entry *tmp;
2031
2032                list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
2033                        list_del(&entry->list_entry);
2034                        devm_kfree(ice_hw_to_dev(hw), entry);
2035                }
2036        }
2037}
2038
2039/**
2040 * ice_cfg_dflt_vsi - change state of VSI to set/clear default
2041 * @hw: pointer to the hardware structure
2042 * @vsi_handle: VSI handle to set as default
2043 * @set: true to add the above mentioned switch rule, false to remove it
2044 * @direction: ICE_FLTR_RX or ICE_FLTR_TX
2045 *
2046 * add filter rule to set/unset given VSI as default VSI for the switch
2047 * (represented by swid)
2048 */
2049enum ice_status
2050ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
2051{
2052        struct ice_aqc_sw_rules_elem *s_rule;
2053        struct ice_fltr_info f_info;
2054        enum ice_adminq_opc opcode;
2055        enum ice_status status;
2056        u16 s_rule_size;
2057        u16 hw_vsi_id;
2058
2059        if (!ice_is_vsi_valid(hw, vsi_handle))
2060                return ICE_ERR_PARAM;
2061        hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2062
2063        s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
2064                ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
2065
2066        s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
2067        if (!s_rule)
2068                return ICE_ERR_NO_MEMORY;
2069
2070        memset(&f_info, 0, sizeof(f_info));
2071
2072        f_info.lkup_type = ICE_SW_LKUP_DFLT;
2073        f_info.flag = direction;
2074        f_info.fltr_act = ICE_FWD_TO_VSI;
2075        f_info.fwd_id.hw_vsi_id = hw_vsi_id;
2076
2077        if (f_info.flag & ICE_FLTR_RX) {
2078                f_info.src = hw->port_info->lport;
2079                f_info.src_id = ICE_SRC_ID_LPORT;
2080                if (!set)
2081                        f_info.fltr_rule_id =
2082                                hw->port_info->dflt_rx_vsi_rule_id;
2083        } else if (f_info.flag & ICE_FLTR_TX) {
2084                f_info.src_id = ICE_SRC_ID_VSI;
2085                f_info.src = hw_vsi_id;
2086                if (!set)
2087                        f_info.fltr_rule_id =
2088                                hw->port_info->dflt_tx_vsi_rule_id;
2089        }
2090
2091        if (set)
2092                opcode = ice_aqc_opc_add_sw_rules;
2093        else
2094                opcode = ice_aqc_opc_remove_sw_rules;
2095
2096        ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
2097
2098        status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
2099        if (status || !(f_info.flag & ICE_FLTR_TX_RX))
2100                goto out;
2101        if (set) {
2102                u16 index = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
2103
2104                if (f_info.flag & ICE_FLTR_TX) {
2105                        hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
2106                        hw->port_info->dflt_tx_vsi_rule_id = index;
2107                } else if (f_info.flag & ICE_FLTR_RX) {
2108                        hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
2109                        hw->port_info->dflt_rx_vsi_rule_id = index;
2110                }
2111        } else {
2112                if (f_info.flag & ICE_FLTR_TX) {
2113                        hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
2114                        hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
2115                } else if (f_info.flag & ICE_FLTR_RX) {
2116                        hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
2117                        hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
2118                }
2119        }
2120
2121out:
2122        devm_kfree(ice_hw_to_dev(hw), s_rule);
2123        return status;
2124}
2125
2126/**
2127 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
2128 * @hw: pointer to the hardware structure
2129 * @recp_id: lookup type for which the specified rule needs to be searched
2130 * @f_info: rule information
2131 *
2132 * Helper function to search for a unicast rule entry - this is to be used
2133 * to remove unicast MAC filter that is not shared with other VSIs on the
2134 * PF switch.
2135 *
2136 * Returns pointer to entry storing the rule if found
2137 */
2138static struct ice_fltr_mgmt_list_entry *
2139ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
2140                          struct ice_fltr_info *f_info)
2141{
2142        struct ice_switch_info *sw = hw->switch_info;
2143        struct ice_fltr_mgmt_list_entry *list_itr;
2144        struct list_head *list_head;
2145
2146        list_head = &sw->recp_list[recp_id].filt_rules;
2147        list_for_each_entry(list_itr, list_head, list_entry) {
2148                if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
2149                            sizeof(f_info->l_data)) &&
2150                    f_info->fwd_id.hw_vsi_id ==
2151                    list_itr->fltr_info.fwd_id.hw_vsi_id &&
2152                    f_info->flag == list_itr->fltr_info.flag)
2153                        return list_itr;
2154        }
2155        return NULL;
2156}
2157
2158/**
2159 * ice_remove_mac - remove a MAC address based filter rule
2160 * @hw: pointer to the hardware structure
2161 * @m_list: list of MAC addresses and forwarding information
2162 *
2163 * This function removes either a MAC filter rule or a specific VSI from a
2164 * VSI list for a multicast MAC address.
2165 *
2166 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
2167 * ice_add_mac. Caller should be aware that this call will only work if all
2168 * the entries passed into m_list were added previously. It will not attempt to
2169 * do a partial remove of entries that were found.
2170 */
2171enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
2172{
2173        struct ice_fltr_list_entry *list_itr, *tmp;
2174        struct mutex *rule_lock; /* Lock to protect filter rule list */
2175
2176        if (!m_list)
2177                return ICE_ERR_PARAM;
2178
2179        rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2180        list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
2181                enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
2182                u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
2183                u16 vsi_handle;
2184
2185                if (l_type != ICE_SW_LKUP_MAC)
2186                        return ICE_ERR_PARAM;
2187
2188                vsi_handle = list_itr->fltr_info.vsi_handle;
2189                if (!ice_is_vsi_valid(hw, vsi_handle))
2190                        return ICE_ERR_PARAM;
2191
2192                list_itr->fltr_info.fwd_id.hw_vsi_id =
2193                                        ice_get_hw_vsi_num(hw, vsi_handle);
2194                if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
2195                        /* Don't remove the unicast address that belongs to
2196                         * another VSI on the switch, since it is not being
2197                         * shared...
2198                         */
2199                        mutex_lock(rule_lock);
2200                        if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
2201                                                       &list_itr->fltr_info)) {
2202                                mutex_unlock(rule_lock);
2203                                return ICE_ERR_DOES_NOT_EXIST;
2204                        }
2205                        mutex_unlock(rule_lock);
2206                }
2207                list_itr->status = ice_remove_rule_internal(hw,
2208                                                            ICE_SW_LKUP_MAC,
2209                                                            list_itr);
2210                if (list_itr->status)
2211                        return list_itr->status;
2212        }
2213        return 0;
2214}
2215
2216/**
2217 * ice_remove_vlan - Remove VLAN based filter rule
2218 * @hw: pointer to the hardware structure
2219 * @v_list: list of VLAN entries and forwarding information
2220 */
2221enum ice_status
2222ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
2223{
2224        struct ice_fltr_list_entry *v_list_itr, *tmp;
2225
2226        if (!v_list || !hw)
2227                return ICE_ERR_PARAM;
2228
2229        list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2230                enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
2231
2232                if (l_type != ICE_SW_LKUP_VLAN)
2233                        return ICE_ERR_PARAM;
2234                v_list_itr->status = ice_remove_rule_internal(hw,
2235                                                              ICE_SW_LKUP_VLAN,
2236                                                              v_list_itr);
2237                if (v_list_itr->status)
2238                        return v_list_itr->status;
2239        }
2240        return 0;
2241}
2242
2243/**
2244 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
2245 * @fm_entry: filter entry to inspect
2246 * @vsi_handle: VSI handle to compare with filter info
2247 */
2248static bool
2249ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
2250{
2251        return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
2252                 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
2253                (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
2254                 fm_entry->vsi_list_info &&
2255                 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
2256}
2257
2258/**
2259 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
2260 * @hw: pointer to the hardware structure
2261 * @vsi_handle: VSI handle to remove filters from
2262 * @vsi_list_head: pointer to the list to add entry to
2263 * @fi: pointer to fltr_info of filter entry to copy & add
2264 *
2265 * Helper function, used when creating a list of filters to remove from
2266 * a specific VSI. The entry added to vsi_list_head is a COPY of the
2267 * original filter entry, with the exception of fltr_info.fltr_act and
2268 * fltr_info.fwd_id fields. These are set such that later logic can
2269 * extract which VSI to remove the fltr from, and pass on that information.
2270 */
2271static enum ice_status
2272ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2273                               struct list_head *vsi_list_head,
2274                               struct ice_fltr_info *fi)
2275{
2276        struct ice_fltr_list_entry *tmp;
2277
2278        /* this memory is freed up in the caller function
2279         * once filters for this VSI are removed
2280         */
2281        tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
2282        if (!tmp)
2283                return ICE_ERR_NO_MEMORY;
2284
2285        tmp->fltr_info = *fi;
2286
2287        /* Overwrite these fields to indicate which VSI to remove filter from,
2288         * so find and remove logic can extract the information from the
2289         * list entries. Note that original entries will still have proper
2290         * values.
2291         */
2292        tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
2293        tmp->fltr_info.vsi_handle = vsi_handle;
2294        tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2295
2296        list_add(&tmp->list_entry, vsi_list_head);
2297
2298        return 0;
2299}
2300
2301/**
2302 * ice_add_to_vsi_fltr_list - Add VSI filters to the list
2303 * @hw: pointer to the hardware structure
2304 * @vsi_handle: VSI handle to remove filters from
2305 * @lkup_list_head: pointer to the list that has certain lookup type filters
2306 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
2307 *
2308 * Locates all filters in lkup_list_head that are used by the given VSI,
2309 * and adds COPIES of those entries to vsi_list_head (intended to be used
2310 * to remove the listed filters).
2311 * Note that this means all entries in vsi_list_head must be explicitly
2312 * deallocated by the caller when done with list.
2313 */
2314static enum ice_status
2315ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2316                         struct list_head *lkup_list_head,
2317                         struct list_head *vsi_list_head)
2318{
2319        struct ice_fltr_mgmt_list_entry *fm_entry;
2320        enum ice_status status = 0;
2321
2322        /* check to make sure VSI ID is valid and within boundary */
2323        if (!ice_is_vsi_valid(hw, vsi_handle))
2324                return ICE_ERR_PARAM;
2325
2326        list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
2327                if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
2328                        continue;
2329
2330                status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2331                                                        vsi_list_head,
2332                                                        &fm_entry->fltr_info);
2333                if (status)
2334                        return status;
2335        }
2336        return status;
2337}
2338
2339/**
2340 * ice_determine_promisc_mask
2341 * @fi: filter info to parse
2342 *
2343 * Helper function to determine which ICE_PROMISC_ mask corresponds
2344 * to given filter into.
2345 */
2346static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
2347{
2348        u16 vid = fi->l_data.mac_vlan.vlan_id;
2349        u8 *macaddr = fi->l_data.mac.mac_addr;
2350        bool is_tx_fltr = false;
2351        u8 promisc_mask = 0;
2352
2353        if (fi->flag == ICE_FLTR_TX)
2354                is_tx_fltr = true;
2355
2356        if (is_broadcast_ether_addr(macaddr))
2357                promisc_mask |= is_tx_fltr ?
2358                        ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
2359        else if (is_multicast_ether_addr(macaddr))
2360                promisc_mask |= is_tx_fltr ?
2361                        ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
2362        else if (is_unicast_ether_addr(macaddr))
2363                promisc_mask |= is_tx_fltr ?
2364                        ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
2365        if (vid)
2366                promisc_mask |= is_tx_fltr ?
2367                        ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
2368
2369        return promisc_mask;
2370}
2371
2372/**
2373 * ice_remove_promisc - Remove promisc based filter rules
2374 * @hw: pointer to the hardware structure
2375 * @recp_id: recipe ID for which the rule needs to removed
2376 * @v_list: list of promisc entries
2377 */
2378static enum ice_status
2379ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
2380                   struct list_head *v_list)
2381{
2382        struct ice_fltr_list_entry *v_list_itr, *tmp;
2383
2384        list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2385                v_list_itr->status =
2386                        ice_remove_rule_internal(hw, recp_id, v_list_itr);
2387                if (v_list_itr->status)
2388                        return v_list_itr->status;
2389        }
2390        return 0;
2391}
2392
2393/**
2394 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
2395 * @hw: pointer to the hardware structure
2396 * @vsi_handle: VSI handle to clear mode
2397 * @promisc_mask: mask of promiscuous config bits to clear
2398 * @vid: VLAN ID to clear VLAN promiscuous
2399 */
2400enum ice_status
2401ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2402                      u16 vid)
2403{
2404        struct ice_switch_info *sw = hw->switch_info;
2405        struct ice_fltr_list_entry *fm_entry, *tmp;
2406        struct list_head remove_list_head;
2407        struct ice_fltr_mgmt_list_entry *itr;
2408        struct list_head *rule_head;
2409        struct mutex *rule_lock;        /* Lock to protect filter rule list */
2410        enum ice_status status = 0;
2411        u8 recipe_id;
2412
2413        if (!ice_is_vsi_valid(hw, vsi_handle))
2414                return ICE_ERR_PARAM;
2415
2416        if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
2417                recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2418        else
2419                recipe_id = ICE_SW_LKUP_PROMISC;
2420
2421        rule_head = &sw->recp_list[recipe_id].filt_rules;
2422        rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
2423
2424        INIT_LIST_HEAD(&remove_list_head);
2425
2426        mutex_lock(rule_lock);
2427        list_for_each_entry(itr, rule_head, list_entry) {
2428                struct ice_fltr_info *fltr_info;
2429                u8 fltr_promisc_mask = 0;
2430
2431                if (!ice_vsi_uses_fltr(itr, vsi_handle))
2432                        continue;
2433                fltr_info = &itr->fltr_info;
2434
2435                if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
2436                    vid != fltr_info->l_data.mac_vlan.vlan_id)
2437                        continue;
2438
2439                fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
2440
2441                /* Skip if filter is not completely specified by given mask */
2442                if (fltr_promisc_mask & ~promisc_mask)
2443                        continue;
2444
2445                status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2446                                                        &remove_list_head,
2447                                                        fltr_info);
2448                if (status) {
2449                        mutex_unlock(rule_lock);
2450                        goto free_fltr_list;
2451                }
2452        }
2453        mutex_unlock(rule_lock);
2454
2455        status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
2456
2457free_fltr_list:
2458        list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2459                list_del(&fm_entry->list_entry);
2460                devm_kfree(ice_hw_to_dev(hw), fm_entry);
2461        }
2462
2463        return status;
2464}
2465
2466/**
2467 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
2468 * @hw: pointer to the hardware structure
2469 * @vsi_handle: VSI handle to configure
2470 * @promisc_mask: mask of promiscuous config bits
2471 * @vid: VLAN ID to set VLAN promiscuous
2472 */
2473enum ice_status
2474ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
2475{
2476        enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
2477        struct ice_fltr_list_entry f_list_entry;
2478        struct ice_fltr_info new_fltr;
2479        enum ice_status status = 0;
2480        bool is_tx_fltr;
2481        u16 hw_vsi_id;
2482        int pkt_type;
2483        u8 recipe_id;
2484
2485        if (!ice_is_vsi_valid(hw, vsi_handle))
2486                return ICE_ERR_PARAM;
2487        hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2488
2489        memset(&new_fltr, 0, sizeof(new_fltr));
2490
2491        if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
2492                new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
2493                new_fltr.l_data.mac_vlan.vlan_id = vid;
2494                recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2495        } else {
2496                new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
2497                recipe_id = ICE_SW_LKUP_PROMISC;
2498        }
2499
2500        /* Separate filters must be set for each direction/packet type
2501         * combination, so we will loop over the mask value, store the
2502         * individual type, and clear it out in the input mask as it
2503         * is found.
2504         */
2505        while (promisc_mask) {
2506                u8 *mac_addr;
2507
2508                pkt_type = 0;
2509                is_tx_fltr = false;
2510
2511                if (promisc_mask & ICE_PROMISC_UCAST_RX) {
2512                        promisc_mask &= ~ICE_PROMISC_UCAST_RX;
2513                        pkt_type = UCAST_FLTR;
2514                } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
2515                        promisc_mask &= ~ICE_PROMISC_UCAST_TX;
2516                        pkt_type = UCAST_FLTR;
2517                        is_tx_fltr = true;
2518                } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
2519                        promisc_mask &= ~ICE_PROMISC_MCAST_RX;
2520                        pkt_type = MCAST_FLTR;
2521                } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
2522                        promisc_mask &= ~ICE_PROMISC_MCAST_TX;
2523                        pkt_type = MCAST_FLTR;
2524                        is_tx_fltr = true;
2525                } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
2526                        promisc_mask &= ~ICE_PROMISC_BCAST_RX;
2527                        pkt_type = BCAST_FLTR;
2528                } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
2529                        promisc_mask &= ~ICE_PROMISC_BCAST_TX;
2530                        pkt_type = BCAST_FLTR;
2531                        is_tx_fltr = true;
2532                }
2533
2534                /* Check for VLAN promiscuous flag */
2535                if (promisc_mask & ICE_PROMISC_VLAN_RX) {
2536                        promisc_mask &= ~ICE_PROMISC_VLAN_RX;
2537                } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
2538                        promisc_mask &= ~ICE_PROMISC_VLAN_TX;
2539                        is_tx_fltr = true;
2540                }
2541
2542                /* Set filter DA based on packet type */
2543                mac_addr = new_fltr.l_data.mac.mac_addr;
2544                if (pkt_type == BCAST_FLTR) {
2545                        eth_broadcast_addr(mac_addr);
2546                } else if (pkt_type == MCAST_FLTR ||
2547                           pkt_type == UCAST_FLTR) {
2548                        /* Use the dummy ether header DA */
2549                        ether_addr_copy(mac_addr, dummy_eth_header);
2550                        if (pkt_type == MCAST_FLTR)
2551                                mac_addr[0] |= 0x1;     /* Set multicast bit */
2552                }
2553
2554                /* Need to reset this to zero for all iterations */
2555                new_fltr.flag = 0;
2556                if (is_tx_fltr) {
2557                        new_fltr.flag |= ICE_FLTR_TX;
2558                        new_fltr.src = hw_vsi_id;
2559                } else {
2560                        new_fltr.flag |= ICE_FLTR_RX;
2561                        new_fltr.src = hw->port_info->lport;
2562                }
2563
2564                new_fltr.fltr_act = ICE_FWD_TO_VSI;
2565                new_fltr.vsi_handle = vsi_handle;
2566                new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
2567                f_list_entry.fltr_info = new_fltr;
2568
2569                status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
2570                if (status)
2571                        goto set_promisc_exit;
2572        }
2573
2574set_promisc_exit:
2575        return status;
2576}
2577
2578/**
2579 * ice_set_vlan_vsi_promisc
2580 * @hw: pointer to the hardware structure
2581 * @vsi_handle: VSI handle to configure
2582 * @promisc_mask: mask of promiscuous config bits
2583 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
2584 *
2585 * Configure VSI with all associated VLANs to given promiscuous mode(s)
2586 */
2587enum ice_status
2588ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2589                         bool rm_vlan_promisc)
2590{
2591        struct ice_switch_info *sw = hw->switch_info;
2592        struct ice_fltr_list_entry *list_itr, *tmp;
2593        struct list_head vsi_list_head;
2594        struct list_head *vlan_head;
2595        struct mutex *vlan_lock; /* Lock to protect filter rule list */
2596        enum ice_status status;
2597        u16 vlan_id;
2598
2599        INIT_LIST_HEAD(&vsi_list_head);
2600        vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
2601        vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
2602        mutex_lock(vlan_lock);
2603        status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
2604                                          &vsi_list_head);
2605        mutex_unlock(vlan_lock);
2606        if (status)
2607                goto free_fltr_list;
2608
2609        list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
2610                vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
2611                if (rm_vlan_promisc)
2612                        status = ice_clear_vsi_promisc(hw, vsi_handle,
2613                                                       promisc_mask, vlan_id);
2614                else
2615                        status = ice_set_vsi_promisc(hw, vsi_handle,
2616                                                     promisc_mask, vlan_id);
2617                if (status)
2618                        break;
2619        }
2620
2621free_fltr_list:
2622        list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
2623                list_del(&list_itr->list_entry);
2624                devm_kfree(ice_hw_to_dev(hw), list_itr);
2625        }
2626        return status;
2627}
2628
2629/**
2630 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
2631 * @hw: pointer to the hardware structure
2632 * @vsi_handle: VSI handle to remove filters from
2633 * @lkup: switch rule filter lookup type
2634 */
2635static void
2636ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
2637                         enum ice_sw_lkup_type lkup)
2638{
2639        struct ice_switch_info *sw = hw->switch_info;
2640        struct ice_fltr_list_entry *fm_entry;
2641        struct list_head remove_list_head;
2642        struct list_head *rule_head;
2643        struct ice_fltr_list_entry *tmp;
2644        struct mutex *rule_lock;        /* Lock to protect filter rule list */
2645        enum ice_status status;
2646
2647        INIT_LIST_HEAD(&remove_list_head);
2648        rule_lock = &sw->recp_list[lkup].filt_rule_lock;
2649        rule_head = &sw->recp_list[lkup].filt_rules;
2650        mutex_lock(rule_lock);
2651        status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
2652                                          &remove_list_head);
2653        mutex_unlock(rule_lock);
2654        if (status)
2655                goto free_fltr_list;
2656
2657        switch (lkup) {
2658        case ICE_SW_LKUP_MAC:
2659                ice_remove_mac(hw, &remove_list_head);
2660                break;
2661        case ICE_SW_LKUP_VLAN:
2662                ice_remove_vlan(hw, &remove_list_head);
2663                break;
2664        case ICE_SW_LKUP_PROMISC:
2665        case ICE_SW_LKUP_PROMISC_VLAN:
2666                ice_remove_promisc(hw, lkup, &remove_list_head);
2667                break;
2668        case ICE_SW_LKUP_MAC_VLAN:
2669        case ICE_SW_LKUP_ETHERTYPE:
2670        case ICE_SW_LKUP_ETHERTYPE_MAC:
2671        case ICE_SW_LKUP_DFLT:
2672        case ICE_SW_LKUP_LAST:
2673        default:
2674                ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
2675                break;
2676        }
2677
2678free_fltr_list:
2679        list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2680                list_del(&fm_entry->list_entry);
2681                devm_kfree(ice_hw_to_dev(hw), fm_entry);
2682        }
2683}
2684
2685/**
2686 * ice_remove_vsi_fltr - Remove all filters for a VSI
2687 * @hw: pointer to the hardware structure
2688 * @vsi_handle: VSI handle to remove filters from
2689 */
2690void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
2691{
2692        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
2693        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
2694        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
2695        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
2696        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
2697        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
2698        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
2699        ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
2700}
2701
2702/**
2703 * ice_alloc_res_cntr - allocating resource counter
2704 * @hw: pointer to the hardware structure
2705 * @type: type of resource
2706 * @alloc_shared: if set it is shared else dedicated
2707 * @num_items: number of entries requested for FD resource type
2708 * @counter_id: counter index returned by AQ call
2709 */
2710enum ice_status
2711ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
2712                   u16 *counter_id)
2713{
2714        struct ice_aqc_alloc_free_res_elem *buf;
2715        enum ice_status status;
2716        u16 buf_len;
2717
2718        /* Allocate resource */
2719        buf_len = struct_size(buf, elem, 1);
2720        buf = kzalloc(buf_len, GFP_KERNEL);
2721        if (!buf)
2722                return ICE_ERR_NO_MEMORY;
2723
2724        buf->num_elems = cpu_to_le16(num_items);
2725        buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
2726                                      ICE_AQC_RES_TYPE_M) | alloc_shared);
2727
2728        status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
2729                                       ice_aqc_opc_alloc_res, NULL);
2730        if (status)
2731                goto exit;
2732
2733        *counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
2734
2735exit:
2736        kfree(buf);
2737        return status;
2738}
2739
2740/**
2741 * ice_free_res_cntr - free resource counter
2742 * @hw: pointer to the hardware structure
2743 * @type: type of resource
2744 * @alloc_shared: if set it is shared else dedicated
2745 * @num_items: number of entries to be freed for FD resource type
2746 * @counter_id: counter ID resource which needs to be freed
2747 */
2748enum ice_status
2749ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
2750                  u16 counter_id)
2751{
2752        struct ice_aqc_alloc_free_res_elem *buf;
2753        enum ice_status status;
2754        u16 buf_len;
2755
2756        /* Free resource */
2757        buf_len = struct_size(buf, elem, 1);
2758        buf = kzalloc(buf_len, GFP_KERNEL);
2759        if (!buf)
2760                return ICE_ERR_NO_MEMORY;
2761
2762        buf->num_elems = cpu_to_le16(num_items);
2763        buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
2764                                      ICE_AQC_RES_TYPE_M) | alloc_shared);
2765        buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
2766
2767        status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
2768                                       ice_aqc_opc_free_res, NULL);
2769        if (status)
2770                ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
2771
2772        kfree(buf);
2773        return status;
2774}
2775
2776/**
2777 * ice_replay_vsi_fltr - Replay filters for requested VSI
2778 * @hw: pointer to the hardware structure
2779 * @vsi_handle: driver VSI handle
2780 * @recp_id: Recipe ID for which rules need to be replayed
2781 * @list_head: list for which filters need to be replayed
2782 *
2783 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
2784 * It is required to pass valid VSI handle.
2785 */
2786static enum ice_status
2787ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
2788                    struct list_head *list_head)
2789{
2790        struct ice_fltr_mgmt_list_entry *itr;
2791        enum ice_status status = 0;
2792        u16 hw_vsi_id;
2793
2794        if (list_empty(list_head))
2795                return status;
2796        hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2797
2798        list_for_each_entry(itr, list_head, list_entry) {
2799                struct ice_fltr_list_entry f_entry;
2800
2801                f_entry.fltr_info = itr->fltr_info;
2802                if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
2803                    itr->fltr_info.vsi_handle == vsi_handle) {
2804                        /* update the src in case it is VSI num */
2805                        if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2806                                f_entry.fltr_info.src = hw_vsi_id;
2807                        status = ice_add_rule_internal(hw, recp_id, &f_entry);
2808                        if (status)
2809                                goto end;
2810                        continue;
2811                }
2812                if (!itr->vsi_list_info ||
2813                    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
2814                        continue;
2815                /* Clearing it so that the logic can add it back */
2816                clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
2817                f_entry.fltr_info.vsi_handle = vsi_handle;
2818                f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
2819                /* update the src in case it is VSI num */
2820                if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2821                        f_entry.fltr_info.src = hw_vsi_id;
2822                if (recp_id == ICE_SW_LKUP_VLAN)
2823                        status = ice_add_vlan_internal(hw, &f_entry);
2824                else
2825                        status = ice_add_rule_internal(hw, recp_id, &f_entry);
2826                if (status)
2827                        goto end;
2828        }
2829end:
2830        return status;
2831}
2832
2833/**
2834 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
2835 * @hw: pointer to the hardware structure
2836 * @vsi_handle: driver VSI handle
2837 *
2838 * Replays filters for requested VSI via vsi_handle.
2839 */
2840enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
2841{
2842        struct ice_switch_info *sw = hw->switch_info;
2843        enum ice_status status = 0;
2844        u8 i;
2845
2846        for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2847                struct list_head *head;
2848
2849                head = &sw->recp_list[i].filt_replay_rules;
2850                status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
2851                if (status)
2852                        return status;
2853        }
2854        return status;
2855}
2856
2857/**
2858 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
2859 * @hw: pointer to the HW struct
2860 *
2861 * Deletes the filter replay rules.
2862 */
2863void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
2864{
2865        struct ice_switch_info *sw = hw->switch_info;
2866        u8 i;
2867
2868        if (!sw)
2869                return;
2870
2871        for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2872                if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
2873                        struct list_head *l_head;
2874
2875                        l_head = &sw->recp_list[i].filt_replay_rules;
2876                        ice_rem_sw_rule_info(hw, l_head);
2877                }
2878        }
2879}
2880