root/drivers/net/ethernet/intel/ice/ice_switch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ice_aq_alloc_free_res
  2. ice_init_def_sw_recp
  3. ice_aq_get_sw_cfg
  4. ice_aq_add_vsi
  5. ice_aq_free_vsi
  6. ice_aq_update_vsi
  7. ice_is_vsi_valid
  8. ice_get_hw_vsi_num
  9. ice_get_vsi_ctx
  10. ice_save_vsi_ctx
  11. ice_clear_vsi_q_ctx
  12. ice_clear_vsi_ctx
  13. ice_clear_all_vsi_ctx
  14. ice_add_vsi
  15. ice_free_vsi
  16. ice_update_vsi
  17. ice_aq_alloc_free_vsi_list
  18. ice_aq_sw_rules
  19. ice_init_port_info
  20. ice_get_initial_sw_cfg
  21. ice_fill_sw_info
  22. ice_fill_sw_rule
  23. ice_add_marker_act
  24. ice_create_vsi_list_map
  25. ice_update_vsi_list_rule
  26. ice_create_vsi_list_rule
  27. ice_create_pkt_fwd_rule
  28. ice_update_pkt_fwd_rule
  29. ice_update_sw_rule_bridge_mode
  30. ice_add_update_vsi_list
  31. ice_find_rule_entry
  32. ice_find_vsi_list_entry
  33. ice_add_rule_internal
  34. ice_remove_vsi_list_rule
  35. ice_rem_update_vsi_list
  36. ice_remove_rule_internal
  37. ice_add_mac
  38. ice_add_vlan_internal
  39. ice_add_vlan
  40. ice_add_eth_mac
  41. ice_remove_eth_mac
  42. ice_rem_sw_rule_info
  43. ice_cfg_dflt_vsi
  44. ice_find_ucast_rule_entry
  45. ice_remove_mac
  46. ice_remove_vlan
  47. ice_vsi_uses_fltr
  48. ice_add_entry_to_vsi_fltr_list
  49. ice_add_to_vsi_fltr_list
  50. ice_determine_promisc_mask
  51. ice_remove_promisc
  52. ice_clear_vsi_promisc
  53. ice_set_vsi_promisc
  54. ice_set_vlan_vsi_promisc
  55. ice_remove_vsi_lkup_fltr
  56. ice_remove_vsi_fltr
  57. ice_replay_vsi_fltr
  58. ice_replay_vsi_all_fltr
  59. ice_rm_all_sw_replay_rule_info

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

/* [<][>][^][v][top][bottom][index][help] */