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