19c20346bSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 29c20346bSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 39c20346bSAnirudh Venkataramanan 49c20346bSAnirudh Venkataramanan #include "ice_switch.h" 59c20346bSAnirudh Venkataramanan 69daf8208SAnirudh Venkataramanan #define ICE_ETH_DA_OFFSET 0 79daf8208SAnirudh Venkataramanan #define ICE_ETH_ETHTYPE_OFFSET 12 89daf8208SAnirudh Venkataramanan #define ICE_ETH_VLAN_TCI_OFFSET 14 99daf8208SAnirudh Venkataramanan #define ICE_MAX_VLAN_ID 0xFFF 109daf8208SAnirudh Venkataramanan 119daf8208SAnirudh Venkataramanan /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem 129daf8208SAnirudh Venkataramanan * struct to configure any switch filter rules. 139daf8208SAnirudh Venkataramanan * {DA (6 bytes), SA(6 bytes), 149daf8208SAnirudh Venkataramanan * Ether type (2 bytes for header without VLAN tag) OR 159daf8208SAnirudh Venkataramanan * VLAN tag (4 bytes for header with VLAN tag) } 169daf8208SAnirudh Venkataramanan * 179daf8208SAnirudh Venkataramanan * Word on Hardcoded values 189daf8208SAnirudh Venkataramanan * byte 0 = 0x2: to identify it as locally administered DA MAC 199daf8208SAnirudh Venkataramanan * byte 6 = 0x2: to identify it as locally administered SA MAC 209daf8208SAnirudh Venkataramanan * byte 12 = 0x81 & byte 13 = 0x00: 219daf8208SAnirudh Venkataramanan * In case of VLAN filter first two bytes defines ether type (0x8100) 22f9867df6SAnirudh Venkataramanan * and remaining two bytes are placeholder for programming a given VLAN ID 239daf8208SAnirudh Venkataramanan * In case of Ether type filter it is treated as header without VLAN tag 249daf8208SAnirudh Venkataramanan * and byte 12 and 13 is used to program a given Ether type instead 259daf8208SAnirudh Venkataramanan */ 269daf8208SAnirudh Venkataramanan #define DUMMY_ETH_HDR_LEN 16 279daf8208SAnirudh Venkataramanan static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 289daf8208SAnirudh Venkataramanan 0x2, 0, 0, 0, 0, 0, 299daf8208SAnirudh Venkataramanan 0x81, 0, 0, 0}; 309daf8208SAnirudh Venkataramanan 319daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \ 3266486d89SBruce Allan (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \ 3366486d89SBruce Allan (DUMMY_ETH_HDR_LEN * \ 3466486d89SBruce Allan sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0]))) 359daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \ 3666486d89SBruce Allan (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr)) 379daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_LG_ACT_SIZE(n) \ 3866486d89SBruce Allan (offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \ 3966486d89SBruce Allan ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0]))) 409daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_VSI_LIST_SIZE(n) \ 4166486d89SBruce Allan (offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \ 4266486d89SBruce Allan ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0]))) 439daf8208SAnirudh Venkataramanan 449daf8208SAnirudh Venkataramanan /** 4580d144c9SAnirudh Venkataramanan * ice_init_def_sw_recp - initialize the recipe book keeping tables 46f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 4780d144c9SAnirudh Venkataramanan * 4880d144c9SAnirudh Venkataramanan * Allocate memory for the entire recipe table and initialize the structures/ 4980d144c9SAnirudh Venkataramanan * entries corresponding to basic recipes. 5080d144c9SAnirudh Venkataramanan */ 512c5492deSBruce Allan enum ice_status ice_init_def_sw_recp(struct ice_hw *hw) 5280d144c9SAnirudh Venkataramanan { 5380d144c9SAnirudh Venkataramanan struct ice_sw_recipe *recps; 5480d144c9SAnirudh Venkataramanan u8 i; 5580d144c9SAnirudh Venkataramanan 5680d144c9SAnirudh Venkataramanan recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES, 57c6dfd690SBruce Allan sizeof(*recps), GFP_KERNEL); 5880d144c9SAnirudh Venkataramanan if (!recps) 5980d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 6080d144c9SAnirudh Venkataramanan 6180d144c9SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 6280d144c9SAnirudh Venkataramanan recps[i].root_rid = i; 6380d144c9SAnirudh Venkataramanan INIT_LIST_HEAD(&recps[i].filt_rules); 64334cb062SAnirudh Venkataramanan INIT_LIST_HEAD(&recps[i].filt_replay_rules); 6580d144c9SAnirudh Venkataramanan mutex_init(&recps[i].filt_rule_lock); 6680d144c9SAnirudh Venkataramanan } 6780d144c9SAnirudh Venkataramanan 6880d144c9SAnirudh Venkataramanan hw->switch_info->recp_list = recps; 6980d144c9SAnirudh Venkataramanan 7080d144c9SAnirudh Venkataramanan return 0; 7180d144c9SAnirudh Venkataramanan } 7280d144c9SAnirudh Venkataramanan 7380d144c9SAnirudh Venkataramanan /** 749c20346bSAnirudh Venkataramanan * ice_aq_get_sw_cfg - get switch configuration 759c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 769c20346bSAnirudh Venkataramanan * @buf: pointer to the result buffer 779c20346bSAnirudh Venkataramanan * @buf_size: length of the buffer available for response 789c20346bSAnirudh Venkataramanan * @req_desc: pointer to requested descriptor 799c20346bSAnirudh Venkataramanan * @num_elems: pointer to number of elements 809c20346bSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 819c20346bSAnirudh Venkataramanan * 82b3c38904SBruce Allan * Get switch configuration (0x0200) to be placed in buf. 839c20346bSAnirudh Venkataramanan * This admin command returns information such as initial VSI/port number 849c20346bSAnirudh Venkataramanan * and switch ID it belongs to. 859c20346bSAnirudh Venkataramanan * 869c20346bSAnirudh Venkataramanan * NOTE: *req_desc is both an input/output parameter. 879c20346bSAnirudh Venkataramanan * The caller of this function first calls this function with *request_desc set 889c20346bSAnirudh Venkataramanan * to 0. If the response from f/w has *req_desc set to 0, all the switch 899c20346bSAnirudh Venkataramanan * configuration information has been returned; if non-zero (meaning not all 909c20346bSAnirudh Venkataramanan * the information was returned), the caller should call this function again 919c20346bSAnirudh Venkataramanan * with *req_desc set to the previous value returned by f/w to get the 929c20346bSAnirudh Venkataramanan * next block of switch configuration information. 939c20346bSAnirudh Venkataramanan * 949c20346bSAnirudh Venkataramanan * *num_elems is output only parameter. This reflects the number of elements 959c20346bSAnirudh Venkataramanan * in response buffer. The caller of this function to use *num_elems while 969c20346bSAnirudh Venkataramanan * parsing the response buffer. 979c20346bSAnirudh Venkataramanan */ 989c20346bSAnirudh Venkataramanan static enum ice_status 99b3c38904SBruce Allan ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf, 1009c20346bSAnirudh Venkataramanan u16 buf_size, u16 *req_desc, u16 *num_elems, 1019c20346bSAnirudh Venkataramanan struct ice_sq_cd *cd) 1029c20346bSAnirudh Venkataramanan { 1039c20346bSAnirudh Venkataramanan struct ice_aqc_get_sw_cfg *cmd; 1049c20346bSAnirudh Venkataramanan struct ice_aq_desc desc; 105b3c38904SBruce Allan enum ice_status status; 1069c20346bSAnirudh Venkataramanan 1079c20346bSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 1089c20346bSAnirudh Venkataramanan cmd = &desc.params.get_sw_conf; 1099c20346bSAnirudh Venkataramanan cmd->element = cpu_to_le16(*req_desc); 1109c20346bSAnirudh Venkataramanan 1119c20346bSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 1129c20346bSAnirudh Venkataramanan if (!status) { 1139c20346bSAnirudh Venkataramanan *req_desc = le16_to_cpu(cmd->element); 1149c20346bSAnirudh Venkataramanan *num_elems = le16_to_cpu(cmd->num_elems); 1159c20346bSAnirudh Venkataramanan } 1169c20346bSAnirudh Venkataramanan 1179c20346bSAnirudh Venkataramanan return status; 1189c20346bSAnirudh Venkataramanan } 1199c20346bSAnirudh Venkataramanan 1203a858ba3SAnirudh Venkataramanan /** 1213a858ba3SAnirudh Venkataramanan * ice_aq_add_vsi 122f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 1233a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 1243a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 1253a858ba3SAnirudh Venkataramanan * 1263a858ba3SAnirudh Venkataramanan * Add a VSI context to the hardware (0x0210) 1273a858ba3SAnirudh Venkataramanan */ 1280f9d5027SAnirudh Venkataramanan static enum ice_status 1293a858ba3SAnirudh Venkataramanan ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1303a858ba3SAnirudh Venkataramanan struct ice_sq_cd *cd) 1313a858ba3SAnirudh Venkataramanan { 1323a858ba3SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *res; 1333a858ba3SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 1343a858ba3SAnirudh Venkataramanan struct ice_aq_desc desc; 1350f9d5027SAnirudh Venkataramanan enum ice_status status; 1363a858ba3SAnirudh Venkataramanan 1373a858ba3SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 1380f9d5027SAnirudh Venkataramanan res = &desc.params.add_update_free_vsi_res; 1393a858ba3SAnirudh Venkataramanan 1403a858ba3SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 1413a858ba3SAnirudh Venkataramanan 1423a858ba3SAnirudh Venkataramanan if (!vsi_ctx->alloc_from_pool) 1433a858ba3SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | 1443a858ba3SAnirudh Venkataramanan ICE_AQ_VSI_IS_VALID); 1451071a835SAnirudh Venkataramanan cmd->vf_id = vsi_ctx->vf_num; 1463a858ba3SAnirudh Venkataramanan 1473a858ba3SAnirudh Venkataramanan cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags); 1483a858ba3SAnirudh Venkataramanan 1493a858ba3SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 1503a858ba3SAnirudh Venkataramanan 1513a858ba3SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1523a858ba3SAnirudh Venkataramanan sizeof(vsi_ctx->info), cd); 1533a858ba3SAnirudh Venkataramanan 1543a858ba3SAnirudh Venkataramanan if (!status) { 1553a858ba3SAnirudh Venkataramanan vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M; 1563a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used); 1573a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free); 1583a858ba3SAnirudh Venkataramanan } 1593a858ba3SAnirudh Venkataramanan 1603a858ba3SAnirudh Venkataramanan return status; 1613a858ba3SAnirudh Venkataramanan } 1623a858ba3SAnirudh Venkataramanan 1633a858ba3SAnirudh Venkataramanan /** 1640f9d5027SAnirudh Venkataramanan * ice_aq_free_vsi 165f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 1660f9d5027SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 1670f9d5027SAnirudh Venkataramanan * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 1680f9d5027SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 1690f9d5027SAnirudh Venkataramanan * 1700f9d5027SAnirudh Venkataramanan * Free VSI context info from hardware (0x0213) 1710f9d5027SAnirudh Venkataramanan */ 1720f9d5027SAnirudh Venkataramanan static enum ice_status 1730f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1740f9d5027SAnirudh Venkataramanan bool keep_vsi_alloc, struct ice_sq_cd *cd) 1750f9d5027SAnirudh Venkataramanan { 1760f9d5027SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *resp; 1770f9d5027SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 1780f9d5027SAnirudh Venkataramanan struct ice_aq_desc desc; 1790f9d5027SAnirudh Venkataramanan enum ice_status status; 1800f9d5027SAnirudh Venkataramanan 1810f9d5027SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 1820f9d5027SAnirudh Venkataramanan resp = &desc.params.add_update_free_vsi_res; 1830f9d5027SAnirudh Venkataramanan 1840f9d5027SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 1850f9d5027SAnirudh Venkataramanan 1860f9d5027SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 1870f9d5027SAnirudh Venkataramanan if (keep_vsi_alloc) 1880f9d5027SAnirudh Venkataramanan cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC); 1890f9d5027SAnirudh Venkataramanan 1900f9d5027SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1910f9d5027SAnirudh Venkataramanan if (!status) { 1920f9d5027SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 1930f9d5027SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 1940f9d5027SAnirudh Venkataramanan } 1950f9d5027SAnirudh Venkataramanan 1960f9d5027SAnirudh Venkataramanan return status; 1970f9d5027SAnirudh Venkataramanan } 1980f9d5027SAnirudh Venkataramanan 1990f9d5027SAnirudh Venkataramanan /** 2003a858ba3SAnirudh Venkataramanan * ice_aq_update_vsi 201f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2023a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 2033a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 2043a858ba3SAnirudh Venkataramanan * 2053a858ba3SAnirudh Venkataramanan * Update VSI context in the hardware (0x0211) 2063a858ba3SAnirudh Venkataramanan */ 2075726ca0eSAnirudh Venkataramanan static enum ice_status 2083a858ba3SAnirudh Venkataramanan ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 2093a858ba3SAnirudh Venkataramanan struct ice_sq_cd *cd) 2103a858ba3SAnirudh Venkataramanan { 2113a858ba3SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *resp; 2123a858ba3SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 2133a858ba3SAnirudh Venkataramanan struct ice_aq_desc desc; 2143a858ba3SAnirudh Venkataramanan enum ice_status status; 2153a858ba3SAnirudh Venkataramanan 2163a858ba3SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 2170f9d5027SAnirudh Venkataramanan resp = &desc.params.add_update_free_vsi_res; 2183a858ba3SAnirudh Venkataramanan 2193a858ba3SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 2203a858ba3SAnirudh Venkataramanan 2213a858ba3SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 2223a858ba3SAnirudh Venkataramanan 2233a858ba3SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 2243a858ba3SAnirudh Venkataramanan 2253a858ba3SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 2263a858ba3SAnirudh Venkataramanan sizeof(vsi_ctx->info), cd); 2273a858ba3SAnirudh Venkataramanan 2283a858ba3SAnirudh Venkataramanan if (!status) { 2293a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 2303a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 2313a858ba3SAnirudh Venkataramanan } 2323a858ba3SAnirudh Venkataramanan 2333a858ba3SAnirudh Venkataramanan return status; 2343a858ba3SAnirudh Venkataramanan } 2353a858ba3SAnirudh Venkataramanan 2363a858ba3SAnirudh Venkataramanan /** 2370f9d5027SAnirudh Venkataramanan * ice_is_vsi_valid - check whether the VSI is valid or not 238f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2390f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2400f9d5027SAnirudh Venkataramanan * 2410f9d5027SAnirudh Venkataramanan * check whether the VSI is valid or not 2420f9d5027SAnirudh Venkataramanan */ 2434fb33f31SAnirudh Venkataramanan bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 2440f9d5027SAnirudh Venkataramanan { 2450f9d5027SAnirudh Venkataramanan return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 2460f9d5027SAnirudh Venkataramanan } 2470f9d5027SAnirudh Venkataramanan 2480f9d5027SAnirudh Venkataramanan /** 249f9867df6SAnirudh Venkataramanan * ice_get_hw_vsi_num - return the HW VSI number 250f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2510f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2520f9d5027SAnirudh Venkataramanan * 253f9867df6SAnirudh Venkataramanan * return the HW VSI number 2540f9d5027SAnirudh Venkataramanan * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 2550f9d5027SAnirudh Venkataramanan */ 2564fb33f31SAnirudh Venkataramanan u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 2570f9d5027SAnirudh Venkataramanan { 2580f9d5027SAnirudh Venkataramanan return hw->vsi_ctx[vsi_handle]->vsi_num; 2590f9d5027SAnirudh Venkataramanan } 2600f9d5027SAnirudh Venkataramanan 2610f9d5027SAnirudh Venkataramanan /** 2620f9d5027SAnirudh Venkataramanan * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 263f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2640f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2650f9d5027SAnirudh Venkataramanan * 2660f9d5027SAnirudh Venkataramanan * return the VSI context entry for a given VSI handle 2670f9d5027SAnirudh Venkataramanan */ 2684fb33f31SAnirudh Venkataramanan struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 2690f9d5027SAnirudh Venkataramanan { 2700f9d5027SAnirudh Venkataramanan return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 2710f9d5027SAnirudh Venkataramanan } 2720f9d5027SAnirudh Venkataramanan 2730f9d5027SAnirudh Venkataramanan /** 2740f9d5027SAnirudh Venkataramanan * ice_save_vsi_ctx - save the VSI context for a given VSI handle 275f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2760f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2770f9d5027SAnirudh Venkataramanan * @vsi: VSI context pointer 2780f9d5027SAnirudh Venkataramanan * 2790f9d5027SAnirudh Venkataramanan * save the VSI context entry for a given VSI handle 2800f9d5027SAnirudh Venkataramanan */ 281c8b7abddSBruce Allan static void 282c8b7abddSBruce Allan ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) 2830f9d5027SAnirudh Venkataramanan { 2840f9d5027SAnirudh Venkataramanan hw->vsi_ctx[vsi_handle] = vsi; 2850f9d5027SAnirudh Venkataramanan } 2860f9d5027SAnirudh Venkataramanan 2870f9d5027SAnirudh Venkataramanan /** 288bb87ee0eSAnirudh Venkataramanan * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs 289bb87ee0eSAnirudh Venkataramanan * @hw: pointer to the HW struct 290bb87ee0eSAnirudh Venkataramanan * @vsi_handle: VSI handle 291bb87ee0eSAnirudh Venkataramanan */ 292bb87ee0eSAnirudh Venkataramanan static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) 293bb87ee0eSAnirudh Venkataramanan { 294bb87ee0eSAnirudh Venkataramanan struct ice_vsi_ctx *vsi; 295bb87ee0eSAnirudh Venkataramanan u8 i; 296bb87ee0eSAnirudh Venkataramanan 297bb87ee0eSAnirudh Venkataramanan vsi = ice_get_vsi_ctx(hw, vsi_handle); 298bb87ee0eSAnirudh Venkataramanan if (!vsi) 299bb87ee0eSAnirudh Venkataramanan return; 300bb87ee0eSAnirudh Venkataramanan ice_for_each_traffic_class(i) { 301bb87ee0eSAnirudh Venkataramanan if (vsi->lan_q_ctx[i]) { 302bb87ee0eSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]); 303bb87ee0eSAnirudh Venkataramanan vsi->lan_q_ctx[i] = NULL; 304bb87ee0eSAnirudh Venkataramanan } 305bb87ee0eSAnirudh Venkataramanan } 306bb87ee0eSAnirudh Venkataramanan } 307bb87ee0eSAnirudh Venkataramanan 308bb87ee0eSAnirudh Venkataramanan /** 3090f9d5027SAnirudh Venkataramanan * ice_clear_vsi_ctx - clear the VSI context entry 310f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 3110f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 3120f9d5027SAnirudh Venkataramanan * 3130f9d5027SAnirudh Venkataramanan * clear the VSI context entry 3140f9d5027SAnirudh Venkataramanan */ 3150f9d5027SAnirudh Venkataramanan static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 3160f9d5027SAnirudh Venkataramanan { 3170f9d5027SAnirudh Venkataramanan struct ice_vsi_ctx *vsi; 3180f9d5027SAnirudh Venkataramanan 3190f9d5027SAnirudh Venkataramanan vsi = ice_get_vsi_ctx(hw, vsi_handle); 3200f9d5027SAnirudh Venkataramanan if (vsi) { 321bb87ee0eSAnirudh Venkataramanan ice_clear_vsi_q_ctx(hw, vsi_handle); 3220f9d5027SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), vsi); 3230f9d5027SAnirudh Venkataramanan hw->vsi_ctx[vsi_handle] = NULL; 3240f9d5027SAnirudh Venkataramanan } 3250f9d5027SAnirudh Venkataramanan } 3260f9d5027SAnirudh Venkataramanan 3270f9d5027SAnirudh Venkataramanan /** 32833e055fcSVictor Raj * ice_clear_all_vsi_ctx - clear all the VSI context entries 329f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 33033e055fcSVictor Raj */ 33133e055fcSVictor Raj void ice_clear_all_vsi_ctx(struct ice_hw *hw) 33233e055fcSVictor Raj { 33333e055fcSVictor Raj u16 i; 33433e055fcSVictor Raj 33533e055fcSVictor Raj for (i = 0; i < ICE_MAX_VSI; i++) 33633e055fcSVictor Raj ice_clear_vsi_ctx(hw, i); 33733e055fcSVictor Raj } 33833e055fcSVictor Raj 33933e055fcSVictor Raj /** 3400f9d5027SAnirudh Venkataramanan * ice_add_vsi - add VSI context to the hardware and VSI handle list 341f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 3420f9d5027SAnirudh Venkataramanan * @vsi_handle: unique VSI handle provided by drivers 3430f9d5027SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 3440f9d5027SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 3450f9d5027SAnirudh Venkataramanan * 3460f9d5027SAnirudh Venkataramanan * Add a VSI context to the hardware also add it into the VSI handle list. 3470f9d5027SAnirudh Venkataramanan * If this function gets called after reset for existing VSIs then update 3480f9d5027SAnirudh Venkataramanan * with the new HW VSI number in the corresponding VSI handle list entry. 3490f9d5027SAnirudh Venkataramanan */ 3500f9d5027SAnirudh Venkataramanan enum ice_status 3510f9d5027SAnirudh Venkataramanan ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 3520f9d5027SAnirudh Venkataramanan struct ice_sq_cd *cd) 3530f9d5027SAnirudh Venkataramanan { 3540f9d5027SAnirudh Venkataramanan struct ice_vsi_ctx *tmp_vsi_ctx; 3550f9d5027SAnirudh Venkataramanan enum ice_status status; 3560f9d5027SAnirudh Venkataramanan 3570f9d5027SAnirudh Venkataramanan if (vsi_handle >= ICE_MAX_VSI) 3580f9d5027SAnirudh Venkataramanan return ICE_ERR_PARAM; 3590f9d5027SAnirudh Venkataramanan status = ice_aq_add_vsi(hw, vsi_ctx, cd); 3600f9d5027SAnirudh Venkataramanan if (status) 3610f9d5027SAnirudh Venkataramanan return status; 3620f9d5027SAnirudh Venkataramanan tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 3630f9d5027SAnirudh Venkataramanan if (!tmp_vsi_ctx) { 364f9867df6SAnirudh Venkataramanan /* Create a new VSI context */ 3650f9d5027SAnirudh Venkataramanan tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw), 3660f9d5027SAnirudh Venkataramanan sizeof(*tmp_vsi_ctx), GFP_KERNEL); 3670f9d5027SAnirudh Venkataramanan if (!tmp_vsi_ctx) { 3680f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(hw, vsi_ctx, false, cd); 3690f9d5027SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 3700f9d5027SAnirudh Venkataramanan } 3710f9d5027SAnirudh Venkataramanan *tmp_vsi_ctx = *vsi_ctx; 3720f9d5027SAnirudh Venkataramanan ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 3730f9d5027SAnirudh Venkataramanan } else { 3740f9d5027SAnirudh Venkataramanan /* update with new HW VSI num */ 3750f9d5027SAnirudh Venkataramanan tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 3760f9d5027SAnirudh Venkataramanan } 3770f9d5027SAnirudh Venkataramanan 3781b5c19c7SBruce Allan return 0; 3790f9d5027SAnirudh Venkataramanan } 3800f9d5027SAnirudh Venkataramanan 3810f9d5027SAnirudh Venkataramanan /** 3820f9d5027SAnirudh Venkataramanan * ice_free_vsi- free VSI context from hardware and VSI handle list 383f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 3840f9d5027SAnirudh Venkataramanan * @vsi_handle: unique VSI handle 3853a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 3863a858ba3SAnirudh Venkataramanan * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 3873a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 3883a858ba3SAnirudh Venkataramanan * 3890f9d5027SAnirudh Venkataramanan * Free VSI context info from hardware as well as from VSI handle list 3903a858ba3SAnirudh Venkataramanan */ 3913a858ba3SAnirudh Venkataramanan enum ice_status 3920f9d5027SAnirudh Venkataramanan ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 3933a858ba3SAnirudh Venkataramanan bool keep_vsi_alloc, struct ice_sq_cd *cd) 3943a858ba3SAnirudh Venkataramanan { 3953a858ba3SAnirudh Venkataramanan enum ice_status status; 3963a858ba3SAnirudh Venkataramanan 3970f9d5027SAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 3980f9d5027SAnirudh Venkataramanan return ICE_ERR_PARAM; 3990f9d5027SAnirudh Venkataramanan vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 4000f9d5027SAnirudh Venkataramanan status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 4010f9d5027SAnirudh Venkataramanan if (!status) 4020f9d5027SAnirudh Venkataramanan ice_clear_vsi_ctx(hw, vsi_handle); 4033a858ba3SAnirudh Venkataramanan return status; 4043a858ba3SAnirudh Venkataramanan } 4053a858ba3SAnirudh Venkataramanan 4069daf8208SAnirudh Venkataramanan /** 4075726ca0eSAnirudh Venkataramanan * ice_update_vsi 408f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 4095726ca0eSAnirudh Venkataramanan * @vsi_handle: unique VSI handle 4105726ca0eSAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 4115726ca0eSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 4125726ca0eSAnirudh Venkataramanan * 4135726ca0eSAnirudh Venkataramanan * Update VSI context in the hardware 4145726ca0eSAnirudh Venkataramanan */ 4155726ca0eSAnirudh Venkataramanan enum ice_status 4165726ca0eSAnirudh Venkataramanan ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 4175726ca0eSAnirudh Venkataramanan struct ice_sq_cd *cd) 4185726ca0eSAnirudh Venkataramanan { 4195726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 4205726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 4215726ca0eSAnirudh Venkataramanan vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 4225726ca0eSAnirudh Venkataramanan return ice_aq_update_vsi(hw, vsi_ctx, cd); 4235726ca0eSAnirudh Venkataramanan } 4245726ca0eSAnirudh Venkataramanan 4255726ca0eSAnirudh Venkataramanan /** 4269daf8208SAnirudh Venkataramanan * ice_aq_alloc_free_vsi_list 427f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 428f9867df6SAnirudh Venkataramanan * @vsi_list_id: VSI list ID returned or used for lookup 4299daf8208SAnirudh Venkataramanan * @lkup_type: switch rule filter lookup type 4309daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 4319daf8208SAnirudh Venkataramanan * 4329daf8208SAnirudh Venkataramanan * allocates or free a VSI list resource 4339daf8208SAnirudh Venkataramanan */ 4349daf8208SAnirudh Venkataramanan static enum ice_status 4359daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 4369daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type, 4379daf8208SAnirudh Venkataramanan enum ice_adminq_opc opc) 4389daf8208SAnirudh Venkataramanan { 4399daf8208SAnirudh Venkataramanan struct ice_aqc_alloc_free_res_elem *sw_buf; 4409daf8208SAnirudh Venkataramanan struct ice_aqc_res_elem *vsi_ele; 4419daf8208SAnirudh Venkataramanan enum ice_status status; 4429daf8208SAnirudh Venkataramanan u16 buf_len; 4439daf8208SAnirudh Venkataramanan 44466486d89SBruce Allan buf_len = struct_size(sw_buf, elem, 1); 4459daf8208SAnirudh Venkataramanan sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL); 4469daf8208SAnirudh Venkataramanan if (!sw_buf) 4479daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 4489daf8208SAnirudh Venkataramanan sw_buf->num_elems = cpu_to_le16(1); 4499daf8208SAnirudh Venkataramanan 4509daf8208SAnirudh Venkataramanan if (lkup_type == ICE_SW_LKUP_MAC || 4519daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_MAC_VLAN || 4529daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE || 4539daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 4549daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC || 4559daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC_VLAN) { 4569daf8208SAnirudh Venkataramanan sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 4579daf8208SAnirudh Venkataramanan } else if (lkup_type == ICE_SW_LKUP_VLAN) { 4589daf8208SAnirudh Venkataramanan sw_buf->res_type = 4599daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 4609daf8208SAnirudh Venkataramanan } else { 4619daf8208SAnirudh Venkataramanan status = ICE_ERR_PARAM; 4629daf8208SAnirudh Venkataramanan goto ice_aq_alloc_free_vsi_list_exit; 4639daf8208SAnirudh Venkataramanan } 4649daf8208SAnirudh Venkataramanan 4659daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_free_res) 4669daf8208SAnirudh Venkataramanan sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id); 4679daf8208SAnirudh Venkataramanan 4689daf8208SAnirudh Venkataramanan status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); 4699daf8208SAnirudh Venkataramanan if (status) 4709daf8208SAnirudh Venkataramanan goto ice_aq_alloc_free_vsi_list_exit; 4719daf8208SAnirudh Venkataramanan 4729daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_alloc_res) { 4739daf8208SAnirudh Venkataramanan vsi_ele = &sw_buf->elem[0]; 4749daf8208SAnirudh Venkataramanan *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp); 4759daf8208SAnirudh Venkataramanan } 4769daf8208SAnirudh Venkataramanan 4779daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list_exit: 4789daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), sw_buf); 4799daf8208SAnirudh Venkataramanan return status; 4809daf8208SAnirudh Venkataramanan } 4819daf8208SAnirudh Venkataramanan 4829daf8208SAnirudh Venkataramanan /** 4839daf8208SAnirudh Venkataramanan * ice_aq_sw_rules - add/update/remove switch rules 484f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 4859daf8208SAnirudh Venkataramanan * @rule_list: pointer to switch rule population list 4869daf8208SAnirudh Venkataramanan * @rule_list_sz: total size of the rule list in bytes 4879daf8208SAnirudh Venkataramanan * @num_rules: number of switch rules in the rule_list 4889daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 4899daf8208SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 4909daf8208SAnirudh Venkataramanan * 4919daf8208SAnirudh Venkataramanan * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 4929daf8208SAnirudh Venkataramanan */ 4939daf8208SAnirudh Venkataramanan static enum ice_status 4949daf8208SAnirudh Venkataramanan ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 4959daf8208SAnirudh Venkataramanan u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 4969daf8208SAnirudh Venkataramanan { 4979daf8208SAnirudh Venkataramanan struct ice_aq_desc desc; 498ca1fdb88SKiran Patil enum ice_status status; 4999daf8208SAnirudh Venkataramanan 5009daf8208SAnirudh Venkataramanan if (opc != ice_aqc_opc_add_sw_rules && 5019daf8208SAnirudh Venkataramanan opc != ice_aqc_opc_update_sw_rules && 5029daf8208SAnirudh Venkataramanan opc != ice_aqc_opc_remove_sw_rules) 5039daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 5049daf8208SAnirudh Venkataramanan 5059daf8208SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, opc); 5069daf8208SAnirudh Venkataramanan 5079daf8208SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 5089daf8208SAnirudh Venkataramanan desc.params.sw_rules.num_rules_fltr_entry_index = 5099daf8208SAnirudh Venkataramanan cpu_to_le16(num_rules); 510ca1fdb88SKiran Patil status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 511ca1fdb88SKiran Patil if (opc != ice_aqc_opc_add_sw_rules && 512ca1fdb88SKiran Patil hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 513ca1fdb88SKiran Patil status = ICE_ERR_DOES_NOT_EXIST; 514ca1fdb88SKiran Patil 515ca1fdb88SKiran Patil return status; 5169daf8208SAnirudh Venkataramanan } 5179daf8208SAnirudh Venkataramanan 5189c20346bSAnirudh Venkataramanan /* ice_init_port_info - Initialize port_info with switch configuration data 5199c20346bSAnirudh Venkataramanan * @pi: pointer to port_info 5209c20346bSAnirudh Venkataramanan * @vsi_port_num: VSI number or port number 5219c20346bSAnirudh Venkataramanan * @type: Type of switch element (port or VSI) 5229c20346bSAnirudh Venkataramanan * @swid: switch ID of the switch the element is attached to 5239c20346bSAnirudh Venkataramanan * @pf_vf_num: PF or VF number 5249c20346bSAnirudh Venkataramanan * @is_vf: true if the element is a VF, false otherwise 5259c20346bSAnirudh Venkataramanan */ 5269c20346bSAnirudh Venkataramanan static void 5279c20346bSAnirudh Venkataramanan ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 5289c20346bSAnirudh Venkataramanan u16 swid, u16 pf_vf_num, bool is_vf) 5299c20346bSAnirudh Venkataramanan { 5309c20346bSAnirudh Venkataramanan switch (type) { 5319c20346bSAnirudh Venkataramanan case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 5329c20346bSAnirudh Venkataramanan pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 5339c20346bSAnirudh Venkataramanan pi->sw_id = swid; 5349c20346bSAnirudh Venkataramanan pi->pf_vf_num = pf_vf_num; 5359c20346bSAnirudh Venkataramanan pi->is_vf = is_vf; 5369c20346bSAnirudh Venkataramanan pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 5379c20346bSAnirudh Venkataramanan pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 5389c20346bSAnirudh Venkataramanan break; 5399c20346bSAnirudh Venkataramanan default: 5409228d8b2SJacob Keller ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n"); 5419c20346bSAnirudh Venkataramanan break; 5429c20346bSAnirudh Venkataramanan } 5439c20346bSAnirudh Venkataramanan } 5449c20346bSAnirudh Venkataramanan 5459c20346bSAnirudh Venkataramanan /* ice_get_initial_sw_cfg - Get initial port and default VSI data 5469c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 5479c20346bSAnirudh Venkataramanan */ 5489c20346bSAnirudh Venkataramanan enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) 5499c20346bSAnirudh Venkataramanan { 550b3c38904SBruce Allan struct ice_aqc_get_sw_cfg_resp_elem *rbuf; 5519c20346bSAnirudh Venkataramanan enum ice_status status; 5529c20346bSAnirudh Venkataramanan u16 req_desc = 0; 5539c20346bSAnirudh Venkataramanan u16 num_elems; 5549c20346bSAnirudh Venkataramanan u16 i; 5559c20346bSAnirudh Venkataramanan 5569c20346bSAnirudh Venkataramanan rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN, 5579c20346bSAnirudh Venkataramanan GFP_KERNEL); 5589c20346bSAnirudh Venkataramanan 5599c20346bSAnirudh Venkataramanan if (!rbuf) 5609c20346bSAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 5619c20346bSAnirudh Venkataramanan 5629c20346bSAnirudh Venkataramanan /* Multiple calls to ice_aq_get_sw_cfg may be required 5639c20346bSAnirudh Venkataramanan * to get all the switch configuration information. The need 5649c20346bSAnirudh Venkataramanan * for additional calls is indicated by ice_aq_get_sw_cfg 5659c20346bSAnirudh Venkataramanan * writing a non-zero value in req_desc 5669c20346bSAnirudh Venkataramanan */ 5679c20346bSAnirudh Venkataramanan do { 568b3c38904SBruce Allan struct ice_aqc_get_sw_cfg_resp_elem *ele; 569b3c38904SBruce Allan 5709c20346bSAnirudh Venkataramanan status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 5719c20346bSAnirudh Venkataramanan &req_desc, &num_elems, NULL); 5729c20346bSAnirudh Venkataramanan 5739c20346bSAnirudh Venkataramanan if (status) 5749c20346bSAnirudh Venkataramanan break; 5759c20346bSAnirudh Venkataramanan 576b3c38904SBruce Allan for (i = 0, ele = rbuf; i < num_elems; i++, ele++) { 5779c20346bSAnirudh Venkataramanan u16 pf_vf_num, swid, vsi_port_num; 5789c20346bSAnirudh Venkataramanan bool is_vf = false; 5796dae8aa0SBruce Allan u8 res_type; 5809c20346bSAnirudh Venkataramanan 5819c20346bSAnirudh Venkataramanan vsi_port_num = le16_to_cpu(ele->vsi_port_num) & 5829c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 5839c20346bSAnirudh Venkataramanan 5849c20346bSAnirudh Venkataramanan pf_vf_num = le16_to_cpu(ele->pf_vf_num) & 5859c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 5869c20346bSAnirudh Venkataramanan 5879c20346bSAnirudh Venkataramanan swid = le16_to_cpu(ele->swid); 5889c20346bSAnirudh Venkataramanan 5899c20346bSAnirudh Venkataramanan if (le16_to_cpu(ele->pf_vf_num) & 5909c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_IS_VF) 5919c20346bSAnirudh Venkataramanan is_vf = true; 5929c20346bSAnirudh Venkataramanan 59388865fc4SKarol Kolacinski res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >> 59488865fc4SKarol Kolacinski ICE_AQC_GET_SW_CONF_RESP_TYPE_S); 5959c20346bSAnirudh Venkataramanan 5966dae8aa0SBruce Allan if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) { 5979c20346bSAnirudh Venkataramanan /* FW VSI is not needed. Just continue. */ 5989c20346bSAnirudh Venkataramanan continue; 5999c20346bSAnirudh Venkataramanan } 6009c20346bSAnirudh Venkataramanan 6019c20346bSAnirudh Venkataramanan ice_init_port_info(hw->port_info, vsi_port_num, 6026dae8aa0SBruce Allan res_type, swid, pf_vf_num, is_vf); 6039c20346bSAnirudh Venkataramanan } 6049c20346bSAnirudh Venkataramanan } while (req_desc && !status); 6059c20346bSAnirudh Venkataramanan 606*7a63dae0SBruce Allan devm_kfree(ice_hw_to_dev(hw), rbuf); 6079c20346bSAnirudh Venkataramanan return status; 6089c20346bSAnirudh Venkataramanan } 6099daf8208SAnirudh Venkataramanan 6109daf8208SAnirudh Venkataramanan /** 6119daf8208SAnirudh Venkataramanan * ice_fill_sw_info - Helper function to populate lb_en and lan_en 6129daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 6136a7e6993SYashaswini Raghuram Prathivadi Bhayankaram * @fi: filter info structure to fill/update 6149daf8208SAnirudh Venkataramanan * 6159daf8208SAnirudh Venkataramanan * This helper function populates the lb_en and lan_en elements of the provided 6169daf8208SAnirudh Venkataramanan * ice_fltr_info struct using the switch's type and characteristics of the 6179daf8208SAnirudh Venkataramanan * switch rule being configured. 6189daf8208SAnirudh Venkataramanan */ 6196a7e6993SYashaswini Raghuram Prathivadi Bhayankaram static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) 6209daf8208SAnirudh Venkataramanan { 6216a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->lb_en = false; 6226a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->lan_en = false; 6236a7e6993SYashaswini Raghuram Prathivadi Bhayankaram if ((fi->flag & ICE_FLTR_TX) && 6246a7e6993SYashaswini Raghuram Prathivadi Bhayankaram (fi->fltr_act == ICE_FWD_TO_VSI || 6256a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->fltr_act == ICE_FWD_TO_VSI_LIST || 6266a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->fltr_act == ICE_FWD_TO_Q || 6276a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->fltr_act == ICE_FWD_TO_QGRP)) { 628b58dafbcSChristopher N Bednarz /* Setting LB for prune actions will result in replicated 629b58dafbcSChristopher N Bednarz * packets to the internal switch that will be dropped. 630b58dafbcSChristopher N Bednarz */ 631b58dafbcSChristopher N Bednarz if (fi->lkup_type != ICE_SW_LKUP_VLAN) 6326a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->lb_en = true; 633b58dafbcSChristopher N Bednarz 634277b3a45SYashaswini Raghuram Prathivadi Bhayankaram /* Set lan_en to TRUE if 6356a7e6993SYashaswini Raghuram Prathivadi Bhayankaram * 1. The switch is a VEB AND 6366a7e6993SYashaswini Raghuram Prathivadi Bhayankaram * 2 63726069b44SYashaswini Raghuram Prathivadi Bhayankaram * 2.1 The lookup is a directional lookup like ethertype, 638f9867df6SAnirudh Venkataramanan * promiscuous, ethertype-MAC, promiscuous-VLAN 63926069b44SYashaswini Raghuram Prathivadi Bhayankaram * and default-port OR 64026069b44SYashaswini Raghuram Prathivadi Bhayankaram * 2.2 The lookup is VLAN, OR 641277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR 642277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC. 6436a7e6993SYashaswini Raghuram Prathivadi Bhayankaram * 644277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * OR 645277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * 646277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * The switch is a VEPA. 647277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * 648277b3a45SYashaswini Raghuram Prathivadi Bhayankaram * In all other cases, the LAN enable has to be set to false. 6496a7e6993SYashaswini Raghuram Prathivadi Bhayankaram */ 650277b3a45SYashaswini Raghuram Prathivadi Bhayankaram if (hw->evb_veb) { 65126069b44SYashaswini Raghuram Prathivadi Bhayankaram if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE || 65226069b44SYashaswini Raghuram Prathivadi Bhayankaram fi->lkup_type == ICE_SW_LKUP_PROMISC || 65326069b44SYashaswini Raghuram Prathivadi Bhayankaram fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 65426069b44SYashaswini Raghuram Prathivadi Bhayankaram fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 655277b3a45SYashaswini Raghuram Prathivadi Bhayankaram fi->lkup_type == ICE_SW_LKUP_DFLT || 65626069b44SYashaswini Raghuram Prathivadi Bhayankaram fi->lkup_type == ICE_SW_LKUP_VLAN || 657277b3a45SYashaswini Raghuram Prathivadi Bhayankaram (fi->lkup_type == ICE_SW_LKUP_MAC && 658277b3a45SYashaswini Raghuram Prathivadi Bhayankaram !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) || 6596a7e6993SYashaswini Raghuram Prathivadi Bhayankaram (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN && 660277b3a45SYashaswini Raghuram Prathivadi Bhayankaram !is_unicast_ether_addr(fi->l_data.mac.mac_addr))) 6616a7e6993SYashaswini Raghuram Prathivadi Bhayankaram fi->lan_en = true; 662277b3a45SYashaswini Raghuram Prathivadi Bhayankaram } else { 663277b3a45SYashaswini Raghuram Prathivadi Bhayankaram fi->lan_en = true; 664277b3a45SYashaswini Raghuram Prathivadi Bhayankaram } 6659daf8208SAnirudh Venkataramanan } 6669daf8208SAnirudh Venkataramanan } 6679daf8208SAnirudh Venkataramanan 6689daf8208SAnirudh Venkataramanan /** 6699daf8208SAnirudh Venkataramanan * ice_fill_sw_rule - Helper function to fill switch rule structure 6709daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 6719daf8208SAnirudh Venkataramanan * @f_info: entry containing packet forwarding information 6729daf8208SAnirudh Venkataramanan * @s_rule: switch rule structure to be filled in based on mac_entry 6739daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 6749daf8208SAnirudh Venkataramanan */ 6759daf8208SAnirudh Venkataramanan static void 6769daf8208SAnirudh Venkataramanan ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 6779daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc) 6789daf8208SAnirudh Venkataramanan { 6799daf8208SAnirudh Venkataramanan u16 vlan_id = ICE_MAX_VLAN_ID + 1; 6809daf8208SAnirudh Venkataramanan void *daddr = NULL; 68174118f7aSZhenning Xiao u16 eth_hdr_sz; 68274118f7aSZhenning Xiao u8 *eth_hdr; 6839daf8208SAnirudh Venkataramanan u32 act = 0; 6849daf8208SAnirudh Venkataramanan __be16 *off; 685be8ff000SAnirudh Venkataramanan u8 q_rgn; 6869daf8208SAnirudh Venkataramanan 6879daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_remove_sw_rules) { 6889daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.act = 0; 6899daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.index = 6909daf8208SAnirudh Venkataramanan cpu_to_le16(f_info->fltr_rule_id); 6919daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.hdr_len = 0; 6929daf8208SAnirudh Venkataramanan return; 6939daf8208SAnirudh Venkataramanan } 6949daf8208SAnirudh Venkataramanan 69574118f7aSZhenning Xiao eth_hdr_sz = sizeof(dummy_eth_header); 69674118f7aSZhenning Xiao eth_hdr = s_rule->pdata.lkup_tx_rx.hdr; 69774118f7aSZhenning Xiao 6989daf8208SAnirudh Venkataramanan /* initialize the ether header with a dummy header */ 69974118f7aSZhenning Xiao memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz); 7009daf8208SAnirudh Venkataramanan ice_fill_sw_info(hw, f_info); 7019daf8208SAnirudh Venkataramanan 7029daf8208SAnirudh Venkataramanan switch (f_info->fltr_act) { 7039daf8208SAnirudh Venkataramanan case ICE_FWD_TO_VSI: 7045726ca0eSAnirudh Venkataramanan act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 7059daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_ID_M; 7069daf8208SAnirudh Venkataramanan if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 7079daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | 7089daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VALID_BIT; 7099daf8208SAnirudh Venkataramanan break; 7109daf8208SAnirudh Venkataramanan case ICE_FWD_TO_VSI_LIST: 7119daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_LIST; 7129daf8208SAnirudh Venkataramanan act |= (f_info->fwd_id.vsi_list_id << 7139daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_LIST_ID_S) & 7149daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_LIST_ID_M; 7159daf8208SAnirudh Venkataramanan if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 7169daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | 7179daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VALID_BIT; 7189daf8208SAnirudh Venkataramanan break; 7199daf8208SAnirudh Venkataramanan case ICE_FWD_TO_Q: 7209daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_TO_Q; 7219daf8208SAnirudh Venkataramanan act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 7229daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_Q_INDEX_M; 7239daf8208SAnirudh Venkataramanan break; 7249daf8208SAnirudh Venkataramanan case ICE_DROP_PACKET: 725be8ff000SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 726be8ff000SAnirudh Venkataramanan ICE_SINGLE_ACT_VALID_BIT; 727be8ff000SAnirudh Venkataramanan break; 728be8ff000SAnirudh Venkataramanan case ICE_FWD_TO_QGRP: 729be8ff000SAnirudh Venkataramanan q_rgn = f_info->qgrp_size > 0 ? 730be8ff000SAnirudh Venkataramanan (u8)ilog2(f_info->qgrp_size) : 0; 731be8ff000SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_TO_Q; 732be8ff000SAnirudh Venkataramanan act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 733be8ff000SAnirudh Venkataramanan ICE_SINGLE_ACT_Q_INDEX_M; 734be8ff000SAnirudh Venkataramanan act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 735be8ff000SAnirudh Venkataramanan ICE_SINGLE_ACT_Q_REGION_M; 7369daf8208SAnirudh Venkataramanan break; 7379daf8208SAnirudh Venkataramanan default: 7389daf8208SAnirudh Venkataramanan return; 7399daf8208SAnirudh Venkataramanan } 7409daf8208SAnirudh Venkataramanan 7419daf8208SAnirudh Venkataramanan if (f_info->lb_en) 7429daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_LB_ENABLE; 7439daf8208SAnirudh Venkataramanan if (f_info->lan_en) 7449daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_LAN_ENABLE; 7459daf8208SAnirudh Venkataramanan 7469daf8208SAnirudh Venkataramanan switch (f_info->lkup_type) { 7479daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC: 7489daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac.mac_addr; 7499daf8208SAnirudh Venkataramanan break; 7509daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_VLAN: 7519daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.vlan.vlan_id; 7529daf8208SAnirudh Venkataramanan if (f_info->fltr_act == ICE_FWD_TO_VSI || 7539daf8208SAnirudh Venkataramanan f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 7549daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_PRUNE; 7559daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 7569daf8208SAnirudh Venkataramanan } 7579daf8208SAnirudh Venkataramanan break; 7589daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE_MAC: 7599daf8208SAnirudh Venkataramanan daddr = f_info->l_data.ethertype_mac.mac_addr; 7604e83fc93SBruce Allan fallthrough; 7619daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE: 762feee3cb3SBruce Allan off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 7639daf8208SAnirudh Venkataramanan *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype); 7649daf8208SAnirudh Venkataramanan break; 7659daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC_VLAN: 7669daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac_vlan.mac_addr; 7679daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.mac_vlan.vlan_id; 7689daf8208SAnirudh Venkataramanan break; 7699daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC_VLAN: 7709daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.mac_vlan.vlan_id; 7714e83fc93SBruce Allan fallthrough; 7729daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC: 7739daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac_vlan.mac_addr; 7749daf8208SAnirudh Venkataramanan break; 7759daf8208SAnirudh Venkataramanan default: 7769daf8208SAnirudh Venkataramanan break; 7779daf8208SAnirudh Venkataramanan } 7789daf8208SAnirudh Venkataramanan 7799daf8208SAnirudh Venkataramanan s_rule->type = (f_info->flag & ICE_FLTR_RX) ? 7809daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) : 7819daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); 7829daf8208SAnirudh Venkataramanan 7839daf8208SAnirudh Venkataramanan /* Recipe set depending on lookup type */ 7849daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(f_info->lkup_type); 7859daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(f_info->src); 7869daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act); 7879daf8208SAnirudh Venkataramanan 7889daf8208SAnirudh Venkataramanan if (daddr) 78974118f7aSZhenning Xiao ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr); 7909daf8208SAnirudh Venkataramanan 7919daf8208SAnirudh Venkataramanan if (!(vlan_id > ICE_MAX_VLAN_ID)) { 792feee3cb3SBruce Allan off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 7939daf8208SAnirudh Venkataramanan *off = cpu_to_be16(vlan_id); 7949daf8208SAnirudh Venkataramanan } 7959daf8208SAnirudh Venkataramanan 7969daf8208SAnirudh Venkataramanan /* Create the switch rule with the final dummy Ethernet header */ 7979daf8208SAnirudh Venkataramanan if (opc != ice_aqc_opc_update_sw_rules) 79874118f7aSZhenning Xiao s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(eth_hdr_sz); 7999daf8208SAnirudh Venkataramanan } 8009daf8208SAnirudh Venkataramanan 8019daf8208SAnirudh Venkataramanan /** 8029daf8208SAnirudh Venkataramanan * ice_add_marker_act 8039daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 8049daf8208SAnirudh Venkataramanan * @m_ent: the management entry for which sw marker needs to be added 8059daf8208SAnirudh Venkataramanan * @sw_marker: sw marker to tag the Rx descriptor with 806f9867df6SAnirudh Venkataramanan * @l_id: large action resource ID 8079daf8208SAnirudh Venkataramanan * 8089daf8208SAnirudh Venkataramanan * Create a large action to hold software marker and update the switch rule 8099daf8208SAnirudh Venkataramanan * entry pointed by m_ent with newly created large action 8109daf8208SAnirudh Venkataramanan */ 8119daf8208SAnirudh Venkataramanan static enum ice_status 8129daf8208SAnirudh Venkataramanan ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 8139daf8208SAnirudh Venkataramanan u16 sw_marker, u16 l_id) 8149daf8208SAnirudh Venkataramanan { 8159daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *lg_act, *rx_tx; 8169daf8208SAnirudh Venkataramanan /* For software marker we need 3 large actions 8179daf8208SAnirudh Venkataramanan * 1. FWD action: FWD TO VSI or VSI LIST 818f9867df6SAnirudh Venkataramanan * 2. GENERIC VALUE action to hold the profile ID 819f9867df6SAnirudh Venkataramanan * 3. GENERIC VALUE action to hold the software marker ID 8209daf8208SAnirudh Venkataramanan */ 8219daf8208SAnirudh Venkataramanan const u16 num_lg_acts = 3; 8229daf8208SAnirudh Venkataramanan enum ice_status status; 8239daf8208SAnirudh Venkataramanan u16 lg_act_size; 8249daf8208SAnirudh Venkataramanan u16 rules_size; 8259daf8208SAnirudh Venkataramanan u32 act; 8265726ca0eSAnirudh Venkataramanan u16 id; 8279daf8208SAnirudh Venkataramanan 8289daf8208SAnirudh Venkataramanan if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 8299daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 8309daf8208SAnirudh Venkataramanan 8319daf8208SAnirudh Venkataramanan /* Create two back-to-back switch rules and submit them to the HW using 8329daf8208SAnirudh Venkataramanan * one memory buffer: 8339daf8208SAnirudh Venkataramanan * 1. Large Action 834d337f2afSAnirudh Venkataramanan * 2. Look up Tx Rx 8359daf8208SAnirudh Venkataramanan */ 8369daf8208SAnirudh Venkataramanan lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts); 8379daf8208SAnirudh Venkataramanan rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 8389daf8208SAnirudh Venkataramanan lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL); 8399daf8208SAnirudh Venkataramanan if (!lg_act) 8409daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 8419daf8208SAnirudh Venkataramanan 8429daf8208SAnirudh Venkataramanan rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size); 8439daf8208SAnirudh Venkataramanan 8449daf8208SAnirudh Venkataramanan /* Fill in the first switch rule i.e. large action */ 8459daf8208SAnirudh Venkataramanan lg_act->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT); 8469daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.index = cpu_to_le16(l_id); 8479daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.size = cpu_to_le16(num_lg_acts); 8489daf8208SAnirudh Venkataramanan 8499daf8208SAnirudh Venkataramanan /* First action VSI forwarding or VSI list forwarding depending on how 8509daf8208SAnirudh Venkataramanan * many VSIs 8519daf8208SAnirudh Venkataramanan */ 8525726ca0eSAnirudh Venkataramanan id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 8535726ca0eSAnirudh Venkataramanan m_ent->fltr_info.fwd_id.hw_vsi_id; 8549daf8208SAnirudh Venkataramanan 8559daf8208SAnirudh Venkataramanan act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 85666486d89SBruce Allan act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M; 8579daf8208SAnirudh Venkataramanan if (m_ent->vsi_count > 1) 8589daf8208SAnirudh Venkataramanan act |= ICE_LG_ACT_VSI_LIST; 8599daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[0] = cpu_to_le32(act); 8609daf8208SAnirudh Venkataramanan 8619daf8208SAnirudh Venkataramanan /* Second action descriptor type */ 8629daf8208SAnirudh Venkataramanan act = ICE_LG_ACT_GENERIC; 8639daf8208SAnirudh Venkataramanan 8649daf8208SAnirudh Venkataramanan act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 8659daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[1] = cpu_to_le32(act); 8669daf8208SAnirudh Venkataramanan 8674381147dSAnirudh Venkataramanan act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 8684381147dSAnirudh Venkataramanan ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 8699daf8208SAnirudh Venkataramanan 8709daf8208SAnirudh Venkataramanan /* Third action Marker value */ 8719daf8208SAnirudh Venkataramanan act |= ICE_LG_ACT_GENERIC; 8729daf8208SAnirudh Venkataramanan act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 8739daf8208SAnirudh Venkataramanan ICE_LG_ACT_GENERIC_VALUE_M; 8749daf8208SAnirudh Venkataramanan 8759daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[2] = cpu_to_le32(act); 8769daf8208SAnirudh Venkataramanan 877d337f2afSAnirudh Venkataramanan /* call the fill switch rule to fill the lookup Tx Rx structure */ 8789daf8208SAnirudh Venkataramanan ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 8799daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules); 8809daf8208SAnirudh Venkataramanan 881f9867df6SAnirudh Venkataramanan /* Update the action to point to the large action ID */ 8829daf8208SAnirudh Venkataramanan rx_tx->pdata.lkup_tx_rx.act = 8839daf8208SAnirudh Venkataramanan cpu_to_le32(ICE_SINGLE_ACT_PTR | 8849daf8208SAnirudh Venkataramanan ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 8859daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_PTR_VAL_M)); 8869daf8208SAnirudh Venkataramanan 887f9867df6SAnirudh Venkataramanan /* Use the filter rule ID of the previously created rule with single 8889daf8208SAnirudh Venkataramanan * act. Once the update happens, hardware will treat this as large 8899daf8208SAnirudh Venkataramanan * action 8909daf8208SAnirudh Venkataramanan */ 8919daf8208SAnirudh Venkataramanan rx_tx->pdata.lkup_tx_rx.index = 8929daf8208SAnirudh Venkataramanan cpu_to_le16(m_ent->fltr_info.fltr_rule_id); 8939daf8208SAnirudh Venkataramanan 8949daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 8959daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, NULL); 8969daf8208SAnirudh Venkataramanan if (!status) { 8979daf8208SAnirudh Venkataramanan m_ent->lg_act_idx = l_id; 8989daf8208SAnirudh Venkataramanan m_ent->sw_marker_id = sw_marker; 8999daf8208SAnirudh Venkataramanan } 9009daf8208SAnirudh Venkataramanan 9019daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), lg_act); 9029daf8208SAnirudh Venkataramanan return status; 9039daf8208SAnirudh Venkataramanan } 9049daf8208SAnirudh Venkataramanan 9059daf8208SAnirudh Venkataramanan /** 9069daf8208SAnirudh Venkataramanan * ice_create_vsi_list_map 9079daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 9085726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 9095726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 910f9867df6SAnirudh Venkataramanan * @vsi_list_id: VSI list ID generated as part of allocate resource 9119daf8208SAnirudh Venkataramanan * 912f9867df6SAnirudh Venkataramanan * Helper function to create a new entry of VSI list ID to VSI mapping 913f9867df6SAnirudh Venkataramanan * using the given VSI list ID 9149daf8208SAnirudh Venkataramanan */ 9159daf8208SAnirudh Venkataramanan static struct ice_vsi_list_map_info * 9165726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 9179daf8208SAnirudh Venkataramanan u16 vsi_list_id) 9189daf8208SAnirudh Venkataramanan { 9199daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 9209daf8208SAnirudh Venkataramanan struct ice_vsi_list_map_info *v_map; 9219daf8208SAnirudh Venkataramanan int i; 9229daf8208SAnirudh Venkataramanan 9239daf8208SAnirudh Venkataramanan v_map = devm_kcalloc(ice_hw_to_dev(hw), 1, sizeof(*v_map), GFP_KERNEL); 9249daf8208SAnirudh Venkataramanan if (!v_map) 9259daf8208SAnirudh Venkataramanan return NULL; 9269daf8208SAnirudh Venkataramanan 9279daf8208SAnirudh Venkataramanan v_map->vsi_list_id = vsi_list_id; 9285726ca0eSAnirudh Venkataramanan v_map->ref_cnt = 1; 9299daf8208SAnirudh Venkataramanan for (i = 0; i < num_vsi; i++) 9305726ca0eSAnirudh Venkataramanan set_bit(vsi_handle_arr[i], v_map->vsi_map); 9319daf8208SAnirudh Venkataramanan 9329daf8208SAnirudh Venkataramanan list_add(&v_map->list_entry, &sw->vsi_list_map_head); 9339daf8208SAnirudh Venkataramanan return v_map; 9349daf8208SAnirudh Venkataramanan } 9359daf8208SAnirudh Venkataramanan 9369daf8208SAnirudh Venkataramanan /** 9379daf8208SAnirudh Venkataramanan * ice_update_vsi_list_rule 9389daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 9395726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to form a VSI list 9405726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 941f9867df6SAnirudh Venkataramanan * @vsi_list_id: VSI list ID generated as part of allocate resource 9429daf8208SAnirudh Venkataramanan * @remove: Boolean value to indicate if this is a remove action 9439daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 9449daf8208SAnirudh Venkataramanan * @lkup_type: lookup type of the filter 9459daf8208SAnirudh Venkataramanan * 9469daf8208SAnirudh Venkataramanan * Call AQ command to add a new switch rule or update existing switch rule 947f9867df6SAnirudh Venkataramanan * using the given VSI list ID 9489daf8208SAnirudh Venkataramanan */ 9499daf8208SAnirudh Venkataramanan static enum ice_status 9505726ca0eSAnirudh Venkataramanan ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 9519daf8208SAnirudh Venkataramanan u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 9529daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type) 9539daf8208SAnirudh Venkataramanan { 9549daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 9559daf8208SAnirudh Venkataramanan enum ice_status status; 9569daf8208SAnirudh Venkataramanan u16 s_rule_size; 9576dae8aa0SBruce Allan u16 rule_type; 9589daf8208SAnirudh Venkataramanan int i; 9599daf8208SAnirudh Venkataramanan 9609daf8208SAnirudh Venkataramanan if (!num_vsi) 9619daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 9629daf8208SAnirudh Venkataramanan 9639daf8208SAnirudh Venkataramanan if (lkup_type == ICE_SW_LKUP_MAC || 9649daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_MAC_VLAN || 9659daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE || 9669daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 9679daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC || 9689daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC_VLAN) 9696dae8aa0SBruce Allan rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 9709daf8208SAnirudh Venkataramanan ICE_AQC_SW_RULES_T_VSI_LIST_SET; 9719daf8208SAnirudh Venkataramanan else if (lkup_type == ICE_SW_LKUP_VLAN) 9726dae8aa0SBruce Allan rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 9739daf8208SAnirudh Venkataramanan ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 9749daf8208SAnirudh Venkataramanan else 9759daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 9769daf8208SAnirudh Venkataramanan 9779daf8208SAnirudh Venkataramanan s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi); 9789daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 9799daf8208SAnirudh Venkataramanan if (!s_rule) 9809daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 9815726ca0eSAnirudh Venkataramanan for (i = 0; i < num_vsi; i++) { 9825726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 9835726ca0eSAnirudh Venkataramanan status = ICE_ERR_PARAM; 9845726ca0eSAnirudh Venkataramanan goto exit; 9855726ca0eSAnirudh Venkataramanan } 9865726ca0eSAnirudh Venkataramanan /* AQ call requires hw_vsi_id(s) */ 9875726ca0eSAnirudh Venkataramanan s_rule->pdata.vsi_list.vsi[i] = 9885726ca0eSAnirudh Venkataramanan cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 9895726ca0eSAnirudh Venkataramanan } 9909daf8208SAnirudh Venkataramanan 9916dae8aa0SBruce Allan s_rule->type = cpu_to_le16(rule_type); 9929daf8208SAnirudh Venkataramanan s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi); 9939daf8208SAnirudh Venkataramanan s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id); 9949daf8208SAnirudh Venkataramanan 9959daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 9969daf8208SAnirudh Venkataramanan 9975726ca0eSAnirudh Venkataramanan exit: 9989daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 9999daf8208SAnirudh Venkataramanan return status; 10009daf8208SAnirudh Venkataramanan } 10019daf8208SAnirudh Venkataramanan 10029daf8208SAnirudh Venkataramanan /** 10039daf8208SAnirudh Venkataramanan * ice_create_vsi_list_rule - Creates and populates a VSI list rule 1004f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 10055726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to form a VSI list 10065726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 10079daf8208SAnirudh Venkataramanan * @vsi_list_id: stores the ID of the VSI list to be created 10089daf8208SAnirudh Venkataramanan * @lkup_type: switch rule filter's lookup type 10099daf8208SAnirudh Venkataramanan */ 10109daf8208SAnirudh Venkataramanan static enum ice_status 10115726ca0eSAnirudh Venkataramanan ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 10129daf8208SAnirudh Venkataramanan u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 10139daf8208SAnirudh Venkataramanan { 10149daf8208SAnirudh Venkataramanan enum ice_status status; 10159daf8208SAnirudh Venkataramanan 10169daf8208SAnirudh Venkataramanan status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 10179daf8208SAnirudh Venkataramanan ice_aqc_opc_alloc_res); 10189daf8208SAnirudh Venkataramanan if (status) 10199daf8208SAnirudh Venkataramanan return status; 10209daf8208SAnirudh Venkataramanan 10219daf8208SAnirudh Venkataramanan /* Update the newly created VSI list to include the specified VSIs */ 10225726ca0eSAnirudh Venkataramanan return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 10235726ca0eSAnirudh Venkataramanan *vsi_list_id, false, 10245726ca0eSAnirudh Venkataramanan ice_aqc_opc_add_sw_rules, lkup_type); 10259daf8208SAnirudh Venkataramanan } 10269daf8208SAnirudh Venkataramanan 10279daf8208SAnirudh Venkataramanan /** 10289daf8208SAnirudh Venkataramanan * ice_create_pkt_fwd_rule 10299daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 10309daf8208SAnirudh Venkataramanan * @f_entry: entry containing packet forwarding information 10319daf8208SAnirudh Venkataramanan * 10329daf8208SAnirudh Venkataramanan * Create switch rule with given filter information and add an entry 10339daf8208SAnirudh Venkataramanan * to the corresponding filter management list to track this switch rule 10349daf8208SAnirudh Venkataramanan * and VSI mapping 10359daf8208SAnirudh Venkataramanan */ 10369daf8208SAnirudh Venkataramanan static enum ice_status 10379daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule(struct ice_hw *hw, 10389daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 10399daf8208SAnirudh Venkataramanan { 10409daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 10419daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 10429daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type l_type; 104380d144c9SAnirudh Venkataramanan struct ice_sw_recipe *recp; 10449daf8208SAnirudh Venkataramanan enum ice_status status; 10459daf8208SAnirudh Venkataramanan 10469daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 10479daf8208SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL); 10489daf8208SAnirudh Venkataramanan if (!s_rule) 10499daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 10509daf8208SAnirudh Venkataramanan fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry), 10519daf8208SAnirudh Venkataramanan GFP_KERNEL); 10529daf8208SAnirudh Venkataramanan if (!fm_entry) { 10539daf8208SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 10549daf8208SAnirudh Venkataramanan goto ice_create_pkt_fwd_rule_exit; 10559daf8208SAnirudh Venkataramanan } 10569daf8208SAnirudh Venkataramanan 10579daf8208SAnirudh Venkataramanan fm_entry->fltr_info = f_entry->fltr_info; 10589daf8208SAnirudh Venkataramanan 10599daf8208SAnirudh Venkataramanan /* Initialize all the fields for the management entry */ 10609daf8208SAnirudh Venkataramanan fm_entry->vsi_count = 1; 10619daf8208SAnirudh Venkataramanan fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 10629daf8208SAnirudh Venkataramanan fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 10639daf8208SAnirudh Venkataramanan fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 10649daf8208SAnirudh Venkataramanan 10659daf8208SAnirudh Venkataramanan ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 10669daf8208SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules); 10679daf8208SAnirudh Venkataramanan 10689daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 10699daf8208SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules, NULL); 10709daf8208SAnirudh Venkataramanan if (status) { 10719daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), fm_entry); 10729daf8208SAnirudh Venkataramanan goto ice_create_pkt_fwd_rule_exit; 10739daf8208SAnirudh Venkataramanan } 10749daf8208SAnirudh Venkataramanan 10759daf8208SAnirudh Venkataramanan f_entry->fltr_info.fltr_rule_id = 10769daf8208SAnirudh Venkataramanan le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 10779daf8208SAnirudh Venkataramanan fm_entry->fltr_info.fltr_rule_id = 10789daf8208SAnirudh Venkataramanan le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 10799daf8208SAnirudh Venkataramanan 10809daf8208SAnirudh Venkataramanan /* The book keeping entries will get removed when base driver 10819daf8208SAnirudh Venkataramanan * calls remove filter AQ command 10829daf8208SAnirudh Venkataramanan */ 10839daf8208SAnirudh Venkataramanan l_type = fm_entry->fltr_info.lkup_type; 108480d144c9SAnirudh Venkataramanan recp = &hw->switch_info->recp_list[l_type]; 108580d144c9SAnirudh Venkataramanan list_add(&fm_entry->list_entry, &recp->filt_rules); 108680d144c9SAnirudh Venkataramanan 10879daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule_exit: 10889daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 10899daf8208SAnirudh Venkataramanan return status; 10909daf8208SAnirudh Venkataramanan } 10919daf8208SAnirudh Venkataramanan 10929daf8208SAnirudh Venkataramanan /** 10939daf8208SAnirudh Venkataramanan * ice_update_pkt_fwd_rule 10949daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 109580d144c9SAnirudh Venkataramanan * @f_info: filter information for switch rule 10969daf8208SAnirudh Venkataramanan * 10979daf8208SAnirudh Venkataramanan * Call AQ command to update a previously created switch rule with a 1098f9867df6SAnirudh Venkataramanan * VSI list ID 10999daf8208SAnirudh Venkataramanan */ 11009daf8208SAnirudh Venkataramanan static enum ice_status 110180d144c9SAnirudh Venkataramanan ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 11029daf8208SAnirudh Venkataramanan { 11039daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 11049daf8208SAnirudh Venkataramanan enum ice_status status; 11059daf8208SAnirudh Venkataramanan 11069daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 11079daf8208SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL); 11089daf8208SAnirudh Venkataramanan if (!s_rule) 11099daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 11109daf8208SAnirudh Venkataramanan 111180d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 11129daf8208SAnirudh Venkataramanan 111380d144c9SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(f_info->fltr_rule_id); 11149daf8208SAnirudh Venkataramanan 11159daf8208SAnirudh Venkataramanan /* Update switch rule with new rule set to forward VSI list */ 11169daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 11179daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, NULL); 11189daf8208SAnirudh Venkataramanan 11199daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 11209daf8208SAnirudh Venkataramanan return status; 11219daf8208SAnirudh Venkataramanan } 11229daf8208SAnirudh Venkataramanan 11239daf8208SAnirudh Venkataramanan /** 1124b1edc14aSMd Fahad Iqbal Polash * ice_update_sw_rule_bridge_mode 1125f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 1126b1edc14aSMd Fahad Iqbal Polash * 1127b1edc14aSMd Fahad Iqbal Polash * Updates unicast switch filter rules based on VEB/VEPA mode 1128b1edc14aSMd Fahad Iqbal Polash */ 1129b1edc14aSMd Fahad Iqbal Polash enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 1130b1edc14aSMd Fahad Iqbal Polash { 1131b1edc14aSMd Fahad Iqbal Polash struct ice_switch_info *sw = hw->switch_info; 1132b1edc14aSMd Fahad Iqbal Polash struct ice_fltr_mgmt_list_entry *fm_entry; 1133b1edc14aSMd Fahad Iqbal Polash enum ice_status status = 0; 1134b1edc14aSMd Fahad Iqbal Polash struct list_head *rule_head; 1135b1edc14aSMd Fahad Iqbal Polash struct mutex *rule_lock; /* Lock to protect filter rule list */ 1136b1edc14aSMd Fahad Iqbal Polash 1137b1edc14aSMd Fahad Iqbal Polash rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 1138b1edc14aSMd Fahad Iqbal Polash rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 1139b1edc14aSMd Fahad Iqbal Polash 1140b1edc14aSMd Fahad Iqbal Polash mutex_lock(rule_lock); 1141b1edc14aSMd Fahad Iqbal Polash list_for_each_entry(fm_entry, rule_head, list_entry) { 1142b1edc14aSMd Fahad Iqbal Polash struct ice_fltr_info *fi = &fm_entry->fltr_info; 1143b1edc14aSMd Fahad Iqbal Polash u8 *addr = fi->l_data.mac.mac_addr; 1144b1edc14aSMd Fahad Iqbal Polash 1145b1edc14aSMd Fahad Iqbal Polash /* Update unicast Tx rules to reflect the selected 1146b1edc14aSMd Fahad Iqbal Polash * VEB/VEPA mode 1147b1edc14aSMd Fahad Iqbal Polash */ 1148b1edc14aSMd Fahad Iqbal Polash if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) && 1149b1edc14aSMd Fahad Iqbal Polash (fi->fltr_act == ICE_FWD_TO_VSI || 1150b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1151b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_Q || 1152b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_QGRP)) { 1153b1edc14aSMd Fahad Iqbal Polash status = ice_update_pkt_fwd_rule(hw, fi); 1154b1edc14aSMd Fahad Iqbal Polash if (status) 1155b1edc14aSMd Fahad Iqbal Polash break; 1156b1edc14aSMd Fahad Iqbal Polash } 1157b1edc14aSMd Fahad Iqbal Polash } 1158b1edc14aSMd Fahad Iqbal Polash 1159b1edc14aSMd Fahad Iqbal Polash mutex_unlock(rule_lock); 1160b1edc14aSMd Fahad Iqbal Polash 1161b1edc14aSMd Fahad Iqbal Polash return status; 1162b1edc14aSMd Fahad Iqbal Polash } 1163b1edc14aSMd Fahad Iqbal Polash 1164b1edc14aSMd Fahad Iqbal Polash /** 116580d144c9SAnirudh Venkataramanan * ice_add_update_vsi_list 11669daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 11679daf8208SAnirudh Venkataramanan * @m_entry: pointer to current filter management list entry 11689daf8208SAnirudh Venkataramanan * @cur_fltr: filter information from the book keeping entry 11699daf8208SAnirudh Venkataramanan * @new_fltr: filter information with the new VSI to be added 11709daf8208SAnirudh Venkataramanan * 11719daf8208SAnirudh Venkataramanan * Call AQ command to add or update previously created VSI list with new VSI. 11729daf8208SAnirudh Venkataramanan * 11739daf8208SAnirudh Venkataramanan * Helper function to do book keeping associated with adding filter information 1174d337f2afSAnirudh Venkataramanan * The algorithm to do the book keeping is described below : 11759daf8208SAnirudh Venkataramanan * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 11769daf8208SAnirudh Venkataramanan * if only one VSI has been added till now 11779daf8208SAnirudh Venkataramanan * Allocate a new VSI list and add two VSIs 11789daf8208SAnirudh Venkataramanan * to this list using switch rule command 11799daf8208SAnirudh Venkataramanan * Update the previously created switch rule with the 1180f9867df6SAnirudh Venkataramanan * newly created VSI list ID 11819daf8208SAnirudh Venkataramanan * if a VSI list was previously created 11829daf8208SAnirudh Venkataramanan * Add the new VSI to the previously created VSI list set 11839daf8208SAnirudh Venkataramanan * using the update switch rule command 11849daf8208SAnirudh Venkataramanan */ 11859daf8208SAnirudh Venkataramanan static enum ice_status 118680d144c9SAnirudh Venkataramanan ice_add_update_vsi_list(struct ice_hw *hw, 11879daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *m_entry, 11889daf8208SAnirudh Venkataramanan struct ice_fltr_info *cur_fltr, 11899daf8208SAnirudh Venkataramanan struct ice_fltr_info *new_fltr) 11909daf8208SAnirudh Venkataramanan { 11919daf8208SAnirudh Venkataramanan enum ice_status status = 0; 11929daf8208SAnirudh Venkataramanan u16 vsi_list_id = 0; 11939daf8208SAnirudh Venkataramanan 11949daf8208SAnirudh Venkataramanan if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 11959daf8208SAnirudh Venkataramanan cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 11969daf8208SAnirudh Venkataramanan return ICE_ERR_NOT_IMPL; 11979daf8208SAnirudh Venkataramanan 11989daf8208SAnirudh Venkataramanan if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 11999daf8208SAnirudh Venkataramanan new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 12009daf8208SAnirudh Venkataramanan (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 12019daf8208SAnirudh Venkataramanan cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 12029daf8208SAnirudh Venkataramanan return ICE_ERR_NOT_IMPL; 12039daf8208SAnirudh Venkataramanan 12049daf8208SAnirudh Venkataramanan if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 12059daf8208SAnirudh Venkataramanan /* Only one entry existed in the mapping and it was not already 12069daf8208SAnirudh Venkataramanan * a part of a VSI list. So, create a VSI list with the old and 12079daf8208SAnirudh Venkataramanan * new VSIs. 12089daf8208SAnirudh Venkataramanan */ 120980d144c9SAnirudh Venkataramanan struct ice_fltr_info tmp_fltr; 12105726ca0eSAnirudh Venkataramanan u16 vsi_handle_arr[2]; 12119daf8208SAnirudh Venkataramanan 12129daf8208SAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 12135726ca0eSAnirudh Venkataramanan if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 12149daf8208SAnirudh Venkataramanan return ICE_ERR_ALREADY_EXISTS; 12159daf8208SAnirudh Venkataramanan 12165726ca0eSAnirudh Venkataramanan vsi_handle_arr[0] = cur_fltr->vsi_handle; 12175726ca0eSAnirudh Venkataramanan vsi_handle_arr[1] = new_fltr->vsi_handle; 12185726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 12199daf8208SAnirudh Venkataramanan &vsi_list_id, 12209daf8208SAnirudh Venkataramanan new_fltr->lkup_type); 12219daf8208SAnirudh Venkataramanan if (status) 12229daf8208SAnirudh Venkataramanan return status; 12239daf8208SAnirudh Venkataramanan 122480d144c9SAnirudh Venkataramanan tmp_fltr = *new_fltr; 122580d144c9SAnirudh Venkataramanan tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 122680d144c9SAnirudh Venkataramanan tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 122780d144c9SAnirudh Venkataramanan tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 12289daf8208SAnirudh Venkataramanan /* Update the previous switch rule of "MAC forward to VSI" to 12299daf8208SAnirudh Venkataramanan * "MAC fwd to VSI list" 12309daf8208SAnirudh Venkataramanan */ 123180d144c9SAnirudh Venkataramanan status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 12329daf8208SAnirudh Venkataramanan if (status) 12339daf8208SAnirudh Venkataramanan return status; 12349daf8208SAnirudh Venkataramanan 12359daf8208SAnirudh Venkataramanan cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 12369daf8208SAnirudh Venkataramanan cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 12379daf8208SAnirudh Venkataramanan m_entry->vsi_list_info = 12385726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 12399daf8208SAnirudh Venkataramanan vsi_list_id); 12409daf8208SAnirudh Venkataramanan 12419daf8208SAnirudh Venkataramanan /* If this entry was large action then the large action needs 12429daf8208SAnirudh Venkataramanan * to be updated to point to FWD to VSI list 12439daf8208SAnirudh Venkataramanan */ 12449daf8208SAnirudh Venkataramanan if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 12459daf8208SAnirudh Venkataramanan status = 12469daf8208SAnirudh Venkataramanan ice_add_marker_act(hw, m_entry, 12479daf8208SAnirudh Venkataramanan m_entry->sw_marker_id, 12489daf8208SAnirudh Venkataramanan m_entry->lg_act_idx); 12499daf8208SAnirudh Venkataramanan } else { 12505726ca0eSAnirudh Venkataramanan u16 vsi_handle = new_fltr->vsi_handle; 12519daf8208SAnirudh Venkataramanan enum ice_adminq_opc opcode; 12529daf8208SAnirudh Venkataramanan 1253f25dad19SBruce Allan if (!m_entry->vsi_list_info) 1254f25dad19SBruce Allan return ICE_ERR_CFG; 1255f25dad19SBruce Allan 12569daf8208SAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 12575726ca0eSAnirudh Venkataramanan if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map)) 12589daf8208SAnirudh Venkataramanan return 0; 12599daf8208SAnirudh Venkataramanan 12609daf8208SAnirudh Venkataramanan /* Update the previously created VSI list set with 1261f9867df6SAnirudh Venkataramanan * the new VSI ID passed in 12629daf8208SAnirudh Venkataramanan */ 12639daf8208SAnirudh Venkataramanan vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 12649daf8208SAnirudh Venkataramanan opcode = ice_aqc_opc_update_sw_rules; 12659daf8208SAnirudh Venkataramanan 12665726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 12675726ca0eSAnirudh Venkataramanan vsi_list_id, false, opcode, 12689daf8208SAnirudh Venkataramanan new_fltr->lkup_type); 1269f9867df6SAnirudh Venkataramanan /* update VSI list mapping info with new VSI ID */ 12709daf8208SAnirudh Venkataramanan if (!status) 12715726ca0eSAnirudh Venkataramanan set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map); 12729daf8208SAnirudh Venkataramanan } 12739daf8208SAnirudh Venkataramanan if (!status) 12749daf8208SAnirudh Venkataramanan m_entry->vsi_count++; 12759daf8208SAnirudh Venkataramanan return status; 12769daf8208SAnirudh Venkataramanan } 12779daf8208SAnirudh Venkataramanan 12789daf8208SAnirudh Venkataramanan /** 127980d144c9SAnirudh Venkataramanan * ice_find_rule_entry - Search a rule entry 12809daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 128180d144c9SAnirudh Venkataramanan * @recp_id: lookup type for which the specified rule needs to be searched 128280d144c9SAnirudh Venkataramanan * @f_info: rule information 12839daf8208SAnirudh Venkataramanan * 128480d144c9SAnirudh Venkataramanan * Helper function to search for a given rule entry 128580d144c9SAnirudh Venkataramanan * Returns pointer to entry storing the rule if found 12869daf8208SAnirudh Venkataramanan */ 12879daf8208SAnirudh Venkataramanan static struct ice_fltr_mgmt_list_entry * 128880d144c9SAnirudh Venkataramanan ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info) 12899daf8208SAnirudh Venkataramanan { 129080d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 12919daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 129280d144c9SAnirudh Venkataramanan struct list_head *list_head; 12939daf8208SAnirudh Venkataramanan 129480d144c9SAnirudh Venkataramanan list_head = &sw->recp_list[recp_id].filt_rules; 129580d144c9SAnirudh Venkataramanan list_for_each_entry(list_itr, list_head, list_entry) { 129680d144c9SAnirudh Venkataramanan if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 129780d144c9SAnirudh Venkataramanan sizeof(f_info->l_data)) && 129880d144c9SAnirudh Venkataramanan f_info->flag == list_itr->fltr_info.flag) { 129980d144c9SAnirudh Venkataramanan ret = list_itr; 13009daf8208SAnirudh Venkataramanan break; 13019daf8208SAnirudh Venkataramanan } 13029daf8208SAnirudh Venkataramanan } 130380d144c9SAnirudh Venkataramanan return ret; 13049daf8208SAnirudh Venkataramanan } 13059daf8208SAnirudh Venkataramanan 13069daf8208SAnirudh Venkataramanan /** 13075726ca0eSAnirudh Venkataramanan * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 13085726ca0eSAnirudh Venkataramanan * @hw: pointer to the hardware structure 13095726ca0eSAnirudh Venkataramanan * @recp_id: lookup type for which VSI lists needs to be searched 13105726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to be found in VSI list 1311f9867df6SAnirudh Venkataramanan * @vsi_list_id: VSI list ID found containing vsi_handle 13125726ca0eSAnirudh Venkataramanan * 13135726ca0eSAnirudh Venkataramanan * Helper function to search a VSI list with single entry containing given VSI 13145726ca0eSAnirudh Venkataramanan * handle element. This can be extended further to search VSI list with more 13155726ca0eSAnirudh Venkataramanan * than 1 vsi_count. Returns pointer to VSI list entry if found. 13165726ca0eSAnirudh Venkataramanan */ 13175726ca0eSAnirudh Venkataramanan static struct ice_vsi_list_map_info * 13185726ca0eSAnirudh Venkataramanan ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, 13195726ca0eSAnirudh Venkataramanan u16 *vsi_list_id) 13205726ca0eSAnirudh Venkataramanan { 13215726ca0eSAnirudh Venkataramanan struct ice_vsi_list_map_info *map_info = NULL; 13225726ca0eSAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 13235726ca0eSAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_itr; 13245726ca0eSAnirudh Venkataramanan struct list_head *list_head; 13255726ca0eSAnirudh Venkataramanan 13265726ca0eSAnirudh Venkataramanan list_head = &sw->recp_list[recp_id].filt_rules; 13275726ca0eSAnirudh Venkataramanan list_for_each_entry(list_itr, list_head, list_entry) { 13285726ca0eSAnirudh Venkataramanan if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) { 13295726ca0eSAnirudh Venkataramanan map_info = list_itr->vsi_list_info; 13305726ca0eSAnirudh Venkataramanan if (test_bit(vsi_handle, map_info->vsi_map)) { 13315726ca0eSAnirudh Venkataramanan *vsi_list_id = map_info->vsi_list_id; 13325726ca0eSAnirudh Venkataramanan return map_info; 13335726ca0eSAnirudh Venkataramanan } 13345726ca0eSAnirudh Venkataramanan } 13355726ca0eSAnirudh Venkataramanan } 13365726ca0eSAnirudh Venkataramanan return NULL; 13375726ca0eSAnirudh Venkataramanan } 13385726ca0eSAnirudh Venkataramanan 13395726ca0eSAnirudh Venkataramanan /** 134080d144c9SAnirudh Venkataramanan * ice_add_rule_internal - add rule for a given lookup type 13419daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 1342f9867df6SAnirudh Venkataramanan * @recp_id: lookup type (recipe ID) for which rule has to be added 13439daf8208SAnirudh Venkataramanan * @f_entry: structure containing MAC forwarding information 13449daf8208SAnirudh Venkataramanan * 134580d144c9SAnirudh Venkataramanan * Adds or updates the rule lists for a given recipe 13469daf8208SAnirudh Venkataramanan */ 13479daf8208SAnirudh Venkataramanan static enum ice_status 134880d144c9SAnirudh Venkataramanan ice_add_rule_internal(struct ice_hw *hw, u8 recp_id, 134980d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 13509daf8208SAnirudh Venkataramanan { 135180d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 13529daf8208SAnirudh Venkataramanan struct ice_fltr_info *new_fltr, *cur_fltr; 13539daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *m_entry; 135480d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 135580d144c9SAnirudh Venkataramanan enum ice_status status = 0; 13569daf8208SAnirudh Venkataramanan 13575726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 13585726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 13595726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 13605726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 13615726ca0eSAnirudh Venkataramanan 136280d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 136380d144c9SAnirudh Venkataramanan 136480d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 13659daf8208SAnirudh Venkataramanan new_fltr = &f_entry->fltr_info; 136680d144c9SAnirudh Venkataramanan if (new_fltr->flag & ICE_FLTR_RX) 136780d144c9SAnirudh Venkataramanan new_fltr->src = hw->port_info->lport; 136880d144c9SAnirudh Venkataramanan else if (new_fltr->flag & ICE_FLTR_TX) 13695726ca0eSAnirudh Venkataramanan new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id; 13709daf8208SAnirudh Venkataramanan 137180d144c9SAnirudh Venkataramanan m_entry = ice_find_rule_entry(hw, recp_id, new_fltr); 137280d144c9SAnirudh Venkataramanan if (!m_entry) { 137380d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 13749daf8208SAnirudh Venkataramanan return ice_create_pkt_fwd_rule(hw, f_entry); 137580d144c9SAnirudh Venkataramanan } 13769daf8208SAnirudh Venkataramanan 13779daf8208SAnirudh Venkataramanan cur_fltr = &m_entry->fltr_info; 137880d144c9SAnirudh Venkataramanan status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 137980d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 13809daf8208SAnirudh Venkataramanan 138180d144c9SAnirudh Venkataramanan return status; 138280d144c9SAnirudh Venkataramanan } 138380d144c9SAnirudh Venkataramanan 138480d144c9SAnirudh Venkataramanan /** 138580d144c9SAnirudh Venkataramanan * ice_remove_vsi_list_rule 138680d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 1387f9867df6SAnirudh Venkataramanan * @vsi_list_id: VSI list ID generated as part of allocate resource 138880d144c9SAnirudh Venkataramanan * @lkup_type: switch rule filter lookup type 138980d144c9SAnirudh Venkataramanan * 139080d144c9SAnirudh Venkataramanan * The VSI list should be emptied before this function is called to remove the 139180d144c9SAnirudh Venkataramanan * VSI list. 139280d144c9SAnirudh Venkataramanan */ 139380d144c9SAnirudh Venkataramanan static enum ice_status 139480d144c9SAnirudh Venkataramanan ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 139580d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type) 139680d144c9SAnirudh Venkataramanan { 139780d144c9SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 139880d144c9SAnirudh Venkataramanan enum ice_status status; 139980d144c9SAnirudh Venkataramanan u16 s_rule_size; 140080d144c9SAnirudh Venkataramanan 140180d144c9SAnirudh Venkataramanan s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0); 140280d144c9SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 140380d144c9SAnirudh Venkataramanan if (!s_rule) 140480d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 140580d144c9SAnirudh Venkataramanan 140680d144c9SAnirudh Venkataramanan s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR); 140780d144c9SAnirudh Venkataramanan s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id); 140880d144c9SAnirudh Venkataramanan 140980d144c9SAnirudh Venkataramanan /* Free the vsi_list resource that we allocated. It is assumed that the 141080d144c9SAnirudh Venkataramanan * list is empty at this point. 141180d144c9SAnirudh Venkataramanan */ 141280d144c9SAnirudh Venkataramanan status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 141380d144c9SAnirudh Venkataramanan ice_aqc_opc_free_res); 141480d144c9SAnirudh Venkataramanan 141580d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 141680d144c9SAnirudh Venkataramanan return status; 141780d144c9SAnirudh Venkataramanan } 141880d144c9SAnirudh Venkataramanan 141980d144c9SAnirudh Venkataramanan /** 142080d144c9SAnirudh Venkataramanan * ice_rem_update_vsi_list 142180d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 14225726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle of the VSI to remove 142380d144c9SAnirudh Venkataramanan * @fm_list: filter management entry for which the VSI list management needs to 142480d144c9SAnirudh Venkataramanan * be done 142580d144c9SAnirudh Venkataramanan */ 142680d144c9SAnirudh Venkataramanan static enum ice_status 14275726ca0eSAnirudh Venkataramanan ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 142880d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_list) 142980d144c9SAnirudh Venkataramanan { 143080d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type; 143180d144c9SAnirudh Venkataramanan enum ice_status status = 0; 143280d144c9SAnirudh Venkataramanan u16 vsi_list_id; 143380d144c9SAnirudh Venkataramanan 143480d144c9SAnirudh Venkataramanan if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 143580d144c9SAnirudh Venkataramanan fm_list->vsi_count == 0) 143680d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 143780d144c9SAnirudh Venkataramanan 143880d144c9SAnirudh Venkataramanan /* A rule with the VSI being removed does not exist */ 14395726ca0eSAnirudh Venkataramanan if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map)) 144080d144c9SAnirudh Venkataramanan return ICE_ERR_DOES_NOT_EXIST; 144180d144c9SAnirudh Venkataramanan 144280d144c9SAnirudh Venkataramanan lkup_type = fm_list->fltr_info.lkup_type; 144380d144c9SAnirudh Venkataramanan vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 14445726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 144580d144c9SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, 144680d144c9SAnirudh Venkataramanan lkup_type); 144780d144c9SAnirudh Venkataramanan if (status) 144880d144c9SAnirudh Venkataramanan return status; 144980d144c9SAnirudh Venkataramanan 145080d144c9SAnirudh Venkataramanan fm_list->vsi_count--; 14515726ca0eSAnirudh Venkataramanan clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 145280d144c9SAnirudh Venkataramanan 1453c60cdb13SBrett Creeley if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 1454c60cdb13SBrett Creeley struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 145580d144c9SAnirudh Venkataramanan struct ice_vsi_list_map_info *vsi_list_info = 145680d144c9SAnirudh Venkataramanan fm_list->vsi_list_info; 14575726ca0eSAnirudh Venkataramanan u16 rem_vsi_handle; 145880d144c9SAnirudh Venkataramanan 14595726ca0eSAnirudh Venkataramanan rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map, 146080d144c9SAnirudh Venkataramanan ICE_MAX_VSI); 14615726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 146280d144c9SAnirudh Venkataramanan return ICE_ERR_OUT_OF_RANGE; 1463c60cdb13SBrett Creeley 1464c60cdb13SBrett Creeley /* Make sure VSI list is empty before removing it below */ 14655726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 146680d144c9SAnirudh Venkataramanan vsi_list_id, true, 146780d144c9SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, 146880d144c9SAnirudh Venkataramanan lkup_type); 146980d144c9SAnirudh Venkataramanan if (status) 147080d144c9SAnirudh Venkataramanan return status; 147180d144c9SAnirudh Venkataramanan 1472c60cdb13SBrett Creeley tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 1473c60cdb13SBrett Creeley tmp_fltr_info.fwd_id.hw_vsi_id = 1474c60cdb13SBrett Creeley ice_get_hw_vsi_num(hw, rem_vsi_handle); 1475c60cdb13SBrett Creeley tmp_fltr_info.vsi_handle = rem_vsi_handle; 1476c60cdb13SBrett Creeley status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 1477c60cdb13SBrett Creeley if (status) { 14789228d8b2SJacob Keller ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 1479c60cdb13SBrett Creeley tmp_fltr_info.fwd_id.hw_vsi_id, status); 1480c60cdb13SBrett Creeley return status; 1481c60cdb13SBrett Creeley } 1482c60cdb13SBrett Creeley 1483c60cdb13SBrett Creeley fm_list->fltr_info = tmp_fltr_info; 1484c60cdb13SBrett Creeley } 1485c60cdb13SBrett Creeley 1486c60cdb13SBrett Creeley if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 1487c60cdb13SBrett Creeley (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 1488c60cdb13SBrett Creeley struct ice_vsi_list_map_info *vsi_list_info = 1489c60cdb13SBrett Creeley fm_list->vsi_list_info; 1490c60cdb13SBrett Creeley 149180d144c9SAnirudh Venkataramanan /* Remove the VSI list since it is no longer used */ 149280d144c9SAnirudh Venkataramanan status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 1493c60cdb13SBrett Creeley if (status) { 14949228d8b2SJacob Keller ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n", 1495c60cdb13SBrett Creeley vsi_list_id, status); 149680d144c9SAnirudh Venkataramanan return status; 1497c60cdb13SBrett Creeley } 149880d144c9SAnirudh Venkataramanan 149980d144c9SAnirudh Venkataramanan list_del(&vsi_list_info->list_entry); 150080d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), vsi_list_info); 150180d144c9SAnirudh Venkataramanan fm_list->vsi_list_info = NULL; 150280d144c9SAnirudh Venkataramanan } 150380d144c9SAnirudh Venkataramanan 150480d144c9SAnirudh Venkataramanan return status; 150580d144c9SAnirudh Venkataramanan } 150680d144c9SAnirudh Venkataramanan 150780d144c9SAnirudh Venkataramanan /** 150880d144c9SAnirudh Venkataramanan * ice_remove_rule_internal - Remove a filter rule of a given type 150980d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 1510f9867df6SAnirudh Venkataramanan * @recp_id: recipe ID for which the rule needs to removed 151180d144c9SAnirudh Venkataramanan * @f_entry: rule entry containing filter information 151280d144c9SAnirudh Venkataramanan */ 151380d144c9SAnirudh Venkataramanan static enum ice_status 151480d144c9SAnirudh Venkataramanan ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id, 151580d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 151680d144c9SAnirudh Venkataramanan { 151780d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 151880d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_elem; 151980d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 152080d144c9SAnirudh Venkataramanan enum ice_status status = 0; 152180d144c9SAnirudh Venkataramanan bool remove_rule = false; 15225726ca0eSAnirudh Venkataramanan u16 vsi_handle; 15235726ca0eSAnirudh Venkataramanan 15245726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 15255726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 15265726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 15275726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 152880d144c9SAnirudh Venkataramanan 152980d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 153080d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 153180d144c9SAnirudh Venkataramanan list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info); 153280d144c9SAnirudh Venkataramanan if (!list_elem) { 153380d144c9SAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 153480d144c9SAnirudh Venkataramanan goto exit; 153580d144c9SAnirudh Venkataramanan } 153680d144c9SAnirudh Venkataramanan 153780d144c9SAnirudh Venkataramanan if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 153880d144c9SAnirudh Venkataramanan remove_rule = true; 15395726ca0eSAnirudh Venkataramanan } else if (!list_elem->vsi_list_info) { 15405726ca0eSAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 15415726ca0eSAnirudh Venkataramanan goto exit; 1542f9264dd6SJacob Keller } else if (list_elem->vsi_list_info->ref_cnt > 1) { 1543f9264dd6SJacob Keller /* a ref_cnt > 1 indicates that the vsi_list is being 1544f9264dd6SJacob Keller * shared by multiple rules. Decrement the ref_cnt and 1545f9264dd6SJacob Keller * remove this rule, but do not modify the list, as it 1546f9264dd6SJacob Keller * is in-use by other rules. 1547f9264dd6SJacob Keller */ 15485726ca0eSAnirudh Venkataramanan list_elem->vsi_list_info->ref_cnt--; 1549f9264dd6SJacob Keller remove_rule = true; 1550f9264dd6SJacob Keller } else { 1551f9264dd6SJacob Keller /* a ref_cnt of 1 indicates the vsi_list is only used 1552f9264dd6SJacob Keller * by one rule. However, the original removal request is only 1553f9264dd6SJacob Keller * for a single VSI. Update the vsi_list first, and only 1554f9264dd6SJacob Keller * remove the rule if there are no further VSIs in this list. 1555f9264dd6SJacob Keller */ 15565726ca0eSAnirudh Venkataramanan vsi_handle = f_entry->fltr_info.vsi_handle; 15575726ca0eSAnirudh Venkataramanan status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 155880d144c9SAnirudh Venkataramanan if (status) 155980d144c9SAnirudh Venkataramanan goto exit; 1560f9867df6SAnirudh Venkataramanan /* if VSI count goes to zero after updating the VSI list */ 156180d144c9SAnirudh Venkataramanan if (list_elem->vsi_count == 0) 156280d144c9SAnirudh Venkataramanan remove_rule = true; 156380d144c9SAnirudh Venkataramanan } 156480d144c9SAnirudh Venkataramanan 156580d144c9SAnirudh Venkataramanan if (remove_rule) { 156680d144c9SAnirudh Venkataramanan /* Remove the lookup rule */ 156780d144c9SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 156880d144c9SAnirudh Venkataramanan 156980d144c9SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 157080d144c9SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 157180d144c9SAnirudh Venkataramanan GFP_KERNEL); 157280d144c9SAnirudh Venkataramanan if (!s_rule) { 157380d144c9SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 157480d144c9SAnirudh Venkataramanan goto exit; 157580d144c9SAnirudh Venkataramanan } 157680d144c9SAnirudh Venkataramanan 157780d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 157880d144c9SAnirudh Venkataramanan ice_aqc_opc_remove_sw_rules); 157980d144c9SAnirudh Venkataramanan 158080d144c9SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, 158180d144c9SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1, 158280d144c9SAnirudh Venkataramanan ice_aqc_opc_remove_sw_rules, NULL); 158380d144c9SAnirudh Venkataramanan 158480d144c9SAnirudh Venkataramanan /* Remove a book keeping from the list */ 158580d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 158680d144c9SAnirudh Venkataramanan 15878132e17dSJeb Cramer if (status) 15888132e17dSJeb Cramer goto exit; 15898132e17dSJeb Cramer 159080d144c9SAnirudh Venkataramanan list_del(&list_elem->list_entry); 159180d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), list_elem); 159280d144c9SAnirudh Venkataramanan } 159380d144c9SAnirudh Venkataramanan exit: 159480d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 159580d144c9SAnirudh Venkataramanan return status; 15969daf8208SAnirudh Venkataramanan } 15979daf8208SAnirudh Venkataramanan 15989daf8208SAnirudh Venkataramanan /** 15999daf8208SAnirudh Venkataramanan * ice_add_mac - Add a MAC address based filter rule 16009daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 16019daf8208SAnirudh Venkataramanan * @m_list: list of MAC addresses and forwarding information 16029daf8208SAnirudh Venkataramanan * 16039daf8208SAnirudh Venkataramanan * IMPORTANT: When the ucast_shared flag is set to false and m_list has 16049daf8208SAnirudh Venkataramanan * multiple unicast addresses, the function assumes that all the 16059daf8208SAnirudh Venkataramanan * addresses are unique in a given add_mac call. It doesn't 16069daf8208SAnirudh Venkataramanan * check for duplicates in this case, removing duplicates from a given 16079daf8208SAnirudh Venkataramanan * list should be taken care of in the caller of this function. 16089daf8208SAnirudh Venkataramanan */ 1609ebb462dcSBruce Allan enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_list) 16109daf8208SAnirudh Venkataramanan { 16119daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule, *r_iter; 16129daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *m_list_itr; 161380d144c9SAnirudh Venkataramanan struct list_head *rule_head; 161488865fc4SKarol Kolacinski u16 total_elem_left, s_rule_size; 161580d144c9SAnirudh Venkataramanan struct ice_switch_info *sw; 161680d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 16179daf8208SAnirudh Venkataramanan enum ice_status status = 0; 16189daf8208SAnirudh Venkataramanan u16 num_unicast = 0; 161988865fc4SKarol Kolacinski u8 elem_sent; 16209daf8208SAnirudh Venkataramanan 16219daf8208SAnirudh Venkataramanan if (!m_list || !hw) 16229daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 16239daf8208SAnirudh Venkataramanan 162480d144c9SAnirudh Venkataramanan s_rule = NULL; 162580d144c9SAnirudh Venkataramanan sw = hw->switch_info; 162680d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 16279daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 16289daf8208SAnirudh Venkataramanan u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 16295726ca0eSAnirudh Venkataramanan u16 vsi_handle; 16305726ca0eSAnirudh Venkataramanan u16 hw_vsi_id; 16319daf8208SAnirudh Venkataramanan 163280d144c9SAnirudh Venkataramanan m_list_itr->fltr_info.flag = ICE_FLTR_TX; 16335726ca0eSAnirudh Venkataramanan vsi_handle = m_list_itr->fltr_info.vsi_handle; 16345726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 16355726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 16365726ca0eSAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 16375726ca0eSAnirudh Venkataramanan m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 1638f9867df6SAnirudh Venkataramanan /* update the src in case it is VSI num */ 16395726ca0eSAnirudh Venkataramanan if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 16405726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 16415726ca0eSAnirudh Venkataramanan m_list_itr->fltr_info.src = hw_vsi_id; 164280d144c9SAnirudh Venkataramanan if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 164380d144c9SAnirudh Venkataramanan is_zero_ether_addr(add)) 16449daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 16459daf8208SAnirudh Venkataramanan if (is_unicast_ether_addr(add) && !hw->ucast_shared) { 16469daf8208SAnirudh Venkataramanan /* Don't overwrite the unicast address */ 164780d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 164880d144c9SAnirudh Venkataramanan if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, 164980d144c9SAnirudh Venkataramanan &m_list_itr->fltr_info)) { 165080d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 16519daf8208SAnirudh Venkataramanan return ICE_ERR_ALREADY_EXISTS; 165280d144c9SAnirudh Venkataramanan } 165380d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 16549daf8208SAnirudh Venkataramanan num_unicast++; 16559daf8208SAnirudh Venkataramanan } else if (is_multicast_ether_addr(add) || 16569daf8208SAnirudh Venkataramanan (is_unicast_ether_addr(add) && hw->ucast_shared)) { 165780d144c9SAnirudh Venkataramanan m_list_itr->status = 165880d144c9SAnirudh Venkataramanan ice_add_rule_internal(hw, ICE_SW_LKUP_MAC, 165980d144c9SAnirudh Venkataramanan m_list_itr); 166080d144c9SAnirudh Venkataramanan if (m_list_itr->status) 166180d144c9SAnirudh Venkataramanan return m_list_itr->status; 16629daf8208SAnirudh Venkataramanan } 16639daf8208SAnirudh Venkataramanan } 16649daf8208SAnirudh Venkataramanan 166580d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 16669daf8208SAnirudh Venkataramanan /* Exit if no suitable entries were found for adding bulk switch rule */ 166780d144c9SAnirudh Venkataramanan if (!num_unicast) { 166880d144c9SAnirudh Venkataramanan status = 0; 166980d144c9SAnirudh Venkataramanan goto ice_add_mac_exit; 167080d144c9SAnirudh Venkataramanan } 167180d144c9SAnirudh Venkataramanan 167280d144c9SAnirudh Venkataramanan rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 16739daf8208SAnirudh Venkataramanan 16749daf8208SAnirudh Venkataramanan /* Allocate switch rule buffer for the bulk update for unicast */ 16759daf8208SAnirudh Venkataramanan s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 16769daf8208SAnirudh Venkataramanan s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size, 16779daf8208SAnirudh Venkataramanan GFP_KERNEL); 167880d144c9SAnirudh Venkataramanan if (!s_rule) { 167980d144c9SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 168080d144c9SAnirudh Venkataramanan goto ice_add_mac_exit; 168180d144c9SAnirudh Venkataramanan } 16829daf8208SAnirudh Venkataramanan 16839daf8208SAnirudh Venkataramanan r_iter = s_rule; 16849daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 16859daf8208SAnirudh Venkataramanan struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 168680d144c9SAnirudh Venkataramanan u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 16879daf8208SAnirudh Venkataramanan 168880d144c9SAnirudh Venkataramanan if (is_unicast_ether_addr(mac_addr)) { 168980d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 169080d144c9SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules); 16919daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 16929daf8208SAnirudh Venkataramanan ((u8 *)r_iter + s_rule_size); 16939daf8208SAnirudh Venkataramanan } 16949daf8208SAnirudh Venkataramanan } 16959daf8208SAnirudh Venkataramanan 16969daf8208SAnirudh Venkataramanan /* Call AQ bulk switch rule update for all unicast addresses */ 16979daf8208SAnirudh Venkataramanan r_iter = s_rule; 16989daf8208SAnirudh Venkataramanan /* Call AQ switch rule in AQ_MAX chunk */ 16999daf8208SAnirudh Venkataramanan for (total_elem_left = num_unicast; total_elem_left > 0; 17009daf8208SAnirudh Venkataramanan total_elem_left -= elem_sent) { 17019daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *entry = r_iter; 17029daf8208SAnirudh Venkataramanan 170388865fc4SKarol Kolacinski elem_sent = min_t(u8, total_elem_left, 170488865fc4SKarol Kolacinski (ICE_AQ_MAX_BUF_LEN / s_rule_size)); 17059daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 17069daf8208SAnirudh Venkataramanan elem_sent, ice_aqc_opc_add_sw_rules, 17079daf8208SAnirudh Venkataramanan NULL); 17089daf8208SAnirudh Venkataramanan if (status) 17099daf8208SAnirudh Venkataramanan goto ice_add_mac_exit; 17109daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 17119daf8208SAnirudh Venkataramanan ((u8 *)r_iter + (elem_sent * s_rule_size)); 17129daf8208SAnirudh Venkataramanan } 17139daf8208SAnirudh Venkataramanan 1714f9867df6SAnirudh Venkataramanan /* Fill up rule ID based on the value returned from FW */ 17159daf8208SAnirudh Venkataramanan r_iter = s_rule; 17169daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 17179daf8208SAnirudh Venkataramanan struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 171880d144c9SAnirudh Venkataramanan u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 17199daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 17209daf8208SAnirudh Venkataramanan 172180d144c9SAnirudh Venkataramanan if (is_unicast_ether_addr(mac_addr)) { 17229daf8208SAnirudh Venkataramanan f_info->fltr_rule_id = 17239daf8208SAnirudh Venkataramanan le16_to_cpu(r_iter->pdata.lkup_tx_rx.index); 17249daf8208SAnirudh Venkataramanan f_info->fltr_act = ICE_FWD_TO_VSI; 17259daf8208SAnirudh Venkataramanan /* Create an entry to track this MAC address */ 17269daf8208SAnirudh Venkataramanan fm_entry = devm_kzalloc(ice_hw_to_dev(hw), 17279daf8208SAnirudh Venkataramanan sizeof(*fm_entry), GFP_KERNEL); 17289daf8208SAnirudh Venkataramanan if (!fm_entry) { 17299daf8208SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 17309daf8208SAnirudh Venkataramanan goto ice_add_mac_exit; 17319daf8208SAnirudh Venkataramanan } 17329daf8208SAnirudh Venkataramanan fm_entry->fltr_info = *f_info; 17339daf8208SAnirudh Venkataramanan fm_entry->vsi_count = 1; 17349daf8208SAnirudh Venkataramanan /* The book keeping entries will get removed when 17359daf8208SAnirudh Venkataramanan * base driver calls remove filter AQ command 17369daf8208SAnirudh Venkataramanan */ 17379daf8208SAnirudh Venkataramanan 173880d144c9SAnirudh Venkataramanan list_add(&fm_entry->list_entry, rule_head); 17399daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 17409daf8208SAnirudh Venkataramanan ((u8 *)r_iter + s_rule_size); 17419daf8208SAnirudh Venkataramanan } 17429daf8208SAnirudh Venkataramanan } 17439daf8208SAnirudh Venkataramanan 17449daf8208SAnirudh Venkataramanan ice_add_mac_exit: 174580d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 174680d144c9SAnirudh Venkataramanan if (s_rule) 17479daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 17489daf8208SAnirudh Venkataramanan return status; 17499daf8208SAnirudh Venkataramanan } 17509daf8208SAnirudh Venkataramanan 17519daf8208SAnirudh Venkataramanan /** 1752d76a60baSAnirudh Venkataramanan * ice_add_vlan_internal - Add one VLAN based filter rule 1753d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 1754d76a60baSAnirudh Venkataramanan * @f_entry: filter entry containing one VLAN information 1755d76a60baSAnirudh Venkataramanan */ 1756d76a60baSAnirudh Venkataramanan static enum ice_status 1757d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry) 1758d76a60baSAnirudh Venkataramanan { 175980d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 1760d76a60baSAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *v_list_itr; 17615726ca0eSAnirudh Venkataramanan struct ice_fltr_info *new_fltr, *cur_fltr; 17625726ca0eSAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type; 17635726ca0eSAnirudh Venkataramanan u16 vsi_list_id = 0, vsi_handle; 176480d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 176580d144c9SAnirudh Venkataramanan enum ice_status status = 0; 1766d76a60baSAnirudh Venkataramanan 17675726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 17685726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 17695726ca0eSAnirudh Venkataramanan 17705726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 17715726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 1772d76a60baSAnirudh Venkataramanan new_fltr = &f_entry->fltr_info; 17735726ca0eSAnirudh Venkataramanan 1774f9867df6SAnirudh Venkataramanan /* VLAN ID should only be 12 bits */ 1775d76a60baSAnirudh Venkataramanan if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 1776d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 1777d76a60baSAnirudh Venkataramanan 17785726ca0eSAnirudh Venkataramanan if (new_fltr->src_id != ICE_SRC_ID_VSI) 17795726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 17805726ca0eSAnirudh Venkataramanan 17815726ca0eSAnirudh Venkataramanan new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 17825726ca0eSAnirudh Venkataramanan lkup_type = new_fltr->lkup_type; 17835726ca0eSAnirudh Venkataramanan vsi_handle = new_fltr->vsi_handle; 178480d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 178580d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 178680d144c9SAnirudh Venkataramanan v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr); 1787d76a60baSAnirudh Venkataramanan if (!v_list_itr) { 17885726ca0eSAnirudh Venkataramanan struct ice_vsi_list_map_info *map_info = NULL; 1789d76a60baSAnirudh Venkataramanan 1790d76a60baSAnirudh Venkataramanan if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 17915726ca0eSAnirudh Venkataramanan /* All VLAN pruning rules use a VSI list. Check if 17925726ca0eSAnirudh Venkataramanan * there is already a VSI list containing VSI that we 17935726ca0eSAnirudh Venkataramanan * want to add. If found, use the same vsi_list_id for 17945726ca0eSAnirudh Venkataramanan * this new VLAN rule or else create a new list. 1795d76a60baSAnirudh Venkataramanan */ 17965726ca0eSAnirudh Venkataramanan map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN, 17975726ca0eSAnirudh Venkataramanan vsi_handle, 17985726ca0eSAnirudh Venkataramanan &vsi_list_id); 17995726ca0eSAnirudh Venkataramanan if (!map_info) { 18005726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, 18015726ca0eSAnirudh Venkataramanan &vsi_handle, 18025726ca0eSAnirudh Venkataramanan 1, 1803d76a60baSAnirudh Venkataramanan &vsi_list_id, 1804d76a60baSAnirudh Venkataramanan lkup_type); 1805d76a60baSAnirudh Venkataramanan if (status) 180680d144c9SAnirudh Venkataramanan goto exit; 18075726ca0eSAnirudh Venkataramanan } 18085726ca0eSAnirudh Venkataramanan /* Convert the action to forwarding to a VSI list. */ 1809d76a60baSAnirudh Venkataramanan new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 1810d76a60baSAnirudh Venkataramanan new_fltr->fwd_id.vsi_list_id = vsi_list_id; 1811d76a60baSAnirudh Venkataramanan } 1812d76a60baSAnirudh Venkataramanan 1813d76a60baSAnirudh Venkataramanan status = ice_create_pkt_fwd_rule(hw, f_entry); 18145726ca0eSAnirudh Venkataramanan if (!status) { 181580d144c9SAnirudh Venkataramanan v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, 181680d144c9SAnirudh Venkataramanan new_fltr); 181780d144c9SAnirudh Venkataramanan if (!v_list_itr) { 181880d144c9SAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 181980d144c9SAnirudh Venkataramanan goto exit; 182080d144c9SAnirudh Venkataramanan } 18215726ca0eSAnirudh Venkataramanan /* reuse VSI list for new rule and increment ref_cnt */ 18225726ca0eSAnirudh Venkataramanan if (map_info) { 18235726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info = map_info; 18245726ca0eSAnirudh Venkataramanan map_info->ref_cnt++; 18255726ca0eSAnirudh Venkataramanan } else { 1826d76a60baSAnirudh Venkataramanan v_list_itr->vsi_list_info = 18275726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle, 18285726ca0eSAnirudh Venkataramanan 1, vsi_list_id); 1829d76a60baSAnirudh Venkataramanan } 18305726ca0eSAnirudh Venkataramanan } 18315726ca0eSAnirudh Venkataramanan } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 1832f9867df6SAnirudh Venkataramanan /* Update existing VSI list to add new VSI ID only if it used 18335726ca0eSAnirudh Venkataramanan * by one VLAN rule. 18345726ca0eSAnirudh Venkataramanan */ 18355726ca0eSAnirudh Venkataramanan cur_fltr = &v_list_itr->fltr_info; 18365726ca0eSAnirudh Venkataramanan status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 18375726ca0eSAnirudh Venkataramanan new_fltr); 18385726ca0eSAnirudh Venkataramanan } else { 18395726ca0eSAnirudh Venkataramanan /* If VLAN rule exists and VSI list being used by this rule is 18405726ca0eSAnirudh Venkataramanan * referenced by more than 1 VLAN rule. Then create a new VSI 18415726ca0eSAnirudh Venkataramanan * list appending previous VSI with new VSI and update existing 1842f9867df6SAnirudh Venkataramanan * VLAN rule to point to new VSI list ID 18435726ca0eSAnirudh Venkataramanan */ 18445726ca0eSAnirudh Venkataramanan struct ice_fltr_info tmp_fltr; 18455726ca0eSAnirudh Venkataramanan u16 vsi_handle_arr[2]; 18465726ca0eSAnirudh Venkataramanan u16 cur_handle; 1847d76a60baSAnirudh Venkataramanan 18485726ca0eSAnirudh Venkataramanan /* Current implementation only supports reusing VSI list with 18495726ca0eSAnirudh Venkataramanan * one VSI count. We should never hit below condition 18505726ca0eSAnirudh Venkataramanan */ 18515726ca0eSAnirudh Venkataramanan if (v_list_itr->vsi_count > 1 && 18525726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info->ref_cnt > 1) { 18539228d8b2SJacob Keller ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 18545726ca0eSAnirudh Venkataramanan status = ICE_ERR_CFG; 185580d144c9SAnirudh Venkataramanan goto exit; 1856d76a60baSAnirudh Venkataramanan } 1857d76a60baSAnirudh Venkataramanan 18585726ca0eSAnirudh Venkataramanan cur_handle = 18595726ca0eSAnirudh Venkataramanan find_first_bit(v_list_itr->vsi_list_info->vsi_map, 18605726ca0eSAnirudh Venkataramanan ICE_MAX_VSI); 18615726ca0eSAnirudh Venkataramanan 18625726ca0eSAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 18635726ca0eSAnirudh Venkataramanan if (cur_handle == vsi_handle) { 18645726ca0eSAnirudh Venkataramanan status = ICE_ERR_ALREADY_EXISTS; 18655726ca0eSAnirudh Venkataramanan goto exit; 18665726ca0eSAnirudh Venkataramanan } 18675726ca0eSAnirudh Venkataramanan 18685726ca0eSAnirudh Venkataramanan vsi_handle_arr[0] = cur_handle; 18695726ca0eSAnirudh Venkataramanan vsi_handle_arr[1] = vsi_handle; 18705726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 18715726ca0eSAnirudh Venkataramanan &vsi_list_id, lkup_type); 18725726ca0eSAnirudh Venkataramanan if (status) 18735726ca0eSAnirudh Venkataramanan goto exit; 18745726ca0eSAnirudh Venkataramanan 18755726ca0eSAnirudh Venkataramanan tmp_fltr = v_list_itr->fltr_info; 18765726ca0eSAnirudh Venkataramanan tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 18775726ca0eSAnirudh Venkataramanan tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 18785726ca0eSAnirudh Venkataramanan tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 18795726ca0eSAnirudh Venkataramanan /* Update the previous switch rule to a new VSI list which 1880df17b7e0SAnirudh Venkataramanan * includes current VSI that is requested 18815726ca0eSAnirudh Venkataramanan */ 18825726ca0eSAnirudh Venkataramanan status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 18835726ca0eSAnirudh Venkataramanan if (status) 18845726ca0eSAnirudh Venkataramanan goto exit; 18855726ca0eSAnirudh Venkataramanan 18865726ca0eSAnirudh Venkataramanan /* before overriding VSI list map info. decrement ref_cnt of 18875726ca0eSAnirudh Venkataramanan * previous VSI list 18885726ca0eSAnirudh Venkataramanan */ 18895726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info->ref_cnt--; 18905726ca0eSAnirudh Venkataramanan 18915726ca0eSAnirudh Venkataramanan /* now update to newly created list */ 18925726ca0eSAnirudh Venkataramanan v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 18935726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info = 18945726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 18955726ca0eSAnirudh Venkataramanan vsi_list_id); 18965726ca0eSAnirudh Venkataramanan v_list_itr->vsi_count++; 18975726ca0eSAnirudh Venkataramanan } 189880d144c9SAnirudh Venkataramanan 189980d144c9SAnirudh Venkataramanan exit: 190080d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 190180d144c9SAnirudh Venkataramanan return status; 1902d76a60baSAnirudh Venkataramanan } 1903d76a60baSAnirudh Venkataramanan 1904d76a60baSAnirudh Venkataramanan /** 1905d76a60baSAnirudh Venkataramanan * ice_add_vlan - Add VLAN based filter rule 1906d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 1907d76a60baSAnirudh Venkataramanan * @v_list: list of VLAN entries and forwarding information 1908d76a60baSAnirudh Venkataramanan */ 1909ebb462dcSBruce Allan enum ice_status ice_add_vlan(struct ice_hw *hw, struct list_head *v_list) 1910d76a60baSAnirudh Venkataramanan { 1911d76a60baSAnirudh Venkataramanan struct ice_fltr_list_entry *v_list_itr; 1912d76a60baSAnirudh Venkataramanan 1913d76a60baSAnirudh Venkataramanan if (!v_list || !hw) 1914d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 1915d76a60baSAnirudh Venkataramanan 1916d76a60baSAnirudh Venkataramanan list_for_each_entry(v_list_itr, v_list, list_entry) { 1917d76a60baSAnirudh Venkataramanan if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 1918d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 191980d144c9SAnirudh Venkataramanan v_list_itr->fltr_info.flag = ICE_FLTR_TX; 192080d144c9SAnirudh Venkataramanan v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr); 192180d144c9SAnirudh Venkataramanan if (v_list_itr->status) 192280d144c9SAnirudh Venkataramanan return v_list_itr->status; 1923d76a60baSAnirudh Venkataramanan } 1924d76a60baSAnirudh Venkataramanan return 0; 1925d76a60baSAnirudh Venkataramanan } 1926d76a60baSAnirudh Venkataramanan 1927d76a60baSAnirudh Venkataramanan /** 1928d95276ceSAkeem G Abodunrin * ice_add_eth_mac - Add ethertype and MAC based filter rule 1929d95276ceSAkeem G Abodunrin * @hw: pointer to the hardware structure 1930d95276ceSAkeem G Abodunrin * @em_list: list of ether type MAC filter, MAC is optional 19312e0e6228SDave Ertman * 19322e0e6228SDave Ertman * This function requires the caller to populate the entries in 19332e0e6228SDave Ertman * the filter list with the necessary fields (including flags to 19342e0e6228SDave Ertman * indicate Tx or Rx rules). 1935d95276ceSAkeem G Abodunrin */ 1936d95276ceSAkeem G Abodunrin enum ice_status 1937d95276ceSAkeem G Abodunrin ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list) 1938d95276ceSAkeem G Abodunrin { 1939d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *em_list_itr; 1940d95276ceSAkeem G Abodunrin 1941d95276ceSAkeem G Abodunrin if (!em_list || !hw) 1942d95276ceSAkeem G Abodunrin return ICE_ERR_PARAM; 1943d95276ceSAkeem G Abodunrin 1944d95276ceSAkeem G Abodunrin list_for_each_entry(em_list_itr, em_list, list_entry) { 1945d95276ceSAkeem G Abodunrin enum ice_sw_lkup_type l_type = 1946d95276ceSAkeem G Abodunrin em_list_itr->fltr_info.lkup_type; 1947d95276ceSAkeem G Abodunrin 1948d95276ceSAkeem G Abodunrin if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 1949d95276ceSAkeem G Abodunrin l_type != ICE_SW_LKUP_ETHERTYPE) 1950d95276ceSAkeem G Abodunrin return ICE_ERR_PARAM; 1951d95276ceSAkeem G Abodunrin 1952d95276ceSAkeem G Abodunrin em_list_itr->status = ice_add_rule_internal(hw, l_type, 1953d95276ceSAkeem G Abodunrin em_list_itr); 1954d95276ceSAkeem G Abodunrin if (em_list_itr->status) 1955d95276ceSAkeem G Abodunrin return em_list_itr->status; 1956d95276ceSAkeem G Abodunrin } 1957d95276ceSAkeem G Abodunrin return 0; 1958d95276ceSAkeem G Abodunrin } 1959d95276ceSAkeem G Abodunrin 1960d95276ceSAkeem G Abodunrin /** 1961d95276ceSAkeem G Abodunrin * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule 1962d95276ceSAkeem G Abodunrin * @hw: pointer to the hardware structure 1963d95276ceSAkeem G Abodunrin * @em_list: list of ethertype or ethertype MAC entries 1964d95276ceSAkeem G Abodunrin */ 1965d95276ceSAkeem G Abodunrin enum ice_status 1966d95276ceSAkeem G Abodunrin ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list) 1967d95276ceSAkeem G Abodunrin { 1968d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *em_list_itr, *tmp; 1969d95276ceSAkeem G Abodunrin 1970d95276ceSAkeem G Abodunrin if (!em_list || !hw) 1971d95276ceSAkeem G Abodunrin return ICE_ERR_PARAM; 1972d95276ceSAkeem G Abodunrin 1973d95276ceSAkeem G Abodunrin list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) { 1974d95276ceSAkeem G Abodunrin enum ice_sw_lkup_type l_type = 1975d95276ceSAkeem G Abodunrin em_list_itr->fltr_info.lkup_type; 1976d95276ceSAkeem G Abodunrin 1977d95276ceSAkeem G Abodunrin if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 1978d95276ceSAkeem G Abodunrin l_type != ICE_SW_LKUP_ETHERTYPE) 1979d95276ceSAkeem G Abodunrin return ICE_ERR_PARAM; 1980d95276ceSAkeem G Abodunrin 1981d95276ceSAkeem G Abodunrin em_list_itr->status = ice_remove_rule_internal(hw, l_type, 1982d95276ceSAkeem G Abodunrin em_list_itr); 1983d95276ceSAkeem G Abodunrin if (em_list_itr->status) 1984d95276ceSAkeem G Abodunrin return em_list_itr->status; 1985d95276ceSAkeem G Abodunrin } 1986d95276ceSAkeem G Abodunrin return 0; 1987d95276ceSAkeem G Abodunrin } 1988d95276ceSAkeem G Abodunrin 1989d95276ceSAkeem G Abodunrin /** 19900f9d5027SAnirudh Venkataramanan * ice_rem_sw_rule_info 19910f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 19920f9d5027SAnirudh Venkataramanan * @rule_head: pointer to the switch list structure that we want to delete 19930f9d5027SAnirudh Venkataramanan */ 19940f9d5027SAnirudh Venkataramanan static void 19950f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head) 19960f9d5027SAnirudh Venkataramanan { 19970f9d5027SAnirudh Venkataramanan if (!list_empty(rule_head)) { 19980f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *entry; 19990f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *tmp; 20000f9d5027SAnirudh Venkataramanan 20010f9d5027SAnirudh Venkataramanan list_for_each_entry_safe(entry, tmp, rule_head, list_entry) { 20020f9d5027SAnirudh Venkataramanan list_del(&entry->list_entry); 20030f9d5027SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), entry); 20040f9d5027SAnirudh Venkataramanan } 20050f9d5027SAnirudh Venkataramanan } 20060f9d5027SAnirudh Venkataramanan } 20070f9d5027SAnirudh Venkataramanan 20080f9d5027SAnirudh Venkataramanan /** 200980d144c9SAnirudh Venkataramanan * ice_cfg_dflt_vsi - change state of VSI to set/clear default 2010e94d4478SAnirudh Venkataramanan * @hw: pointer to the hardware structure 20115726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to set as default 2012e94d4478SAnirudh Venkataramanan * @set: true to add the above mentioned switch rule, false to remove it 2013e94d4478SAnirudh Venkataramanan * @direction: ICE_FLTR_RX or ICE_FLTR_TX 201480d144c9SAnirudh Venkataramanan * 201580d144c9SAnirudh Venkataramanan * add filter rule to set/unset given VSI as default VSI for the switch 201680d144c9SAnirudh Venkataramanan * (represented by swid) 2017e94d4478SAnirudh Venkataramanan */ 2018e94d4478SAnirudh Venkataramanan enum ice_status 20195726ca0eSAnirudh Venkataramanan ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction) 2020e94d4478SAnirudh Venkataramanan { 2021e94d4478SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 2022e94d4478SAnirudh Venkataramanan struct ice_fltr_info f_info; 2023e94d4478SAnirudh Venkataramanan enum ice_adminq_opc opcode; 2024e94d4478SAnirudh Venkataramanan enum ice_status status; 2025e94d4478SAnirudh Venkataramanan u16 s_rule_size; 20265726ca0eSAnirudh Venkataramanan u16 hw_vsi_id; 20275726ca0eSAnirudh Venkataramanan 20285726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 20295726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 20305726ca0eSAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2031e94d4478SAnirudh Venkataramanan 2032e94d4478SAnirudh Venkataramanan s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE : 2033e94d4478SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE; 203466486d89SBruce Allan 2035e94d4478SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 2036e94d4478SAnirudh Venkataramanan if (!s_rule) 2037e94d4478SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 2038e94d4478SAnirudh Venkataramanan 2039e94d4478SAnirudh Venkataramanan memset(&f_info, 0, sizeof(f_info)); 2040e94d4478SAnirudh Venkataramanan 2041e94d4478SAnirudh Venkataramanan f_info.lkup_type = ICE_SW_LKUP_DFLT; 2042e94d4478SAnirudh Venkataramanan f_info.flag = direction; 2043e94d4478SAnirudh Venkataramanan f_info.fltr_act = ICE_FWD_TO_VSI; 20445726ca0eSAnirudh Venkataramanan f_info.fwd_id.hw_vsi_id = hw_vsi_id; 2045e94d4478SAnirudh Venkataramanan 2046e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_RX) { 2047e94d4478SAnirudh Venkataramanan f_info.src = hw->port_info->lport; 20485726ca0eSAnirudh Venkataramanan f_info.src_id = ICE_SRC_ID_LPORT; 2049e94d4478SAnirudh Venkataramanan if (!set) 2050e94d4478SAnirudh Venkataramanan f_info.fltr_rule_id = 2051e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id; 2052e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_TX) { 20535726ca0eSAnirudh Venkataramanan f_info.src_id = ICE_SRC_ID_VSI; 20545726ca0eSAnirudh Venkataramanan f_info.src = hw_vsi_id; 2055e94d4478SAnirudh Venkataramanan if (!set) 2056e94d4478SAnirudh Venkataramanan f_info.fltr_rule_id = 2057e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id; 2058e94d4478SAnirudh Venkataramanan } 2059e94d4478SAnirudh Venkataramanan 2060e94d4478SAnirudh Venkataramanan if (set) 2061e94d4478SAnirudh Venkataramanan opcode = ice_aqc_opc_add_sw_rules; 2062e94d4478SAnirudh Venkataramanan else 2063e94d4478SAnirudh Venkataramanan opcode = ice_aqc_opc_remove_sw_rules; 2064e94d4478SAnirudh Venkataramanan 2065e94d4478SAnirudh Venkataramanan ice_fill_sw_rule(hw, &f_info, s_rule, opcode); 2066e94d4478SAnirudh Venkataramanan 2067e94d4478SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL); 2068e94d4478SAnirudh Venkataramanan if (status || !(f_info.flag & ICE_FLTR_TX_RX)) 2069e94d4478SAnirudh Venkataramanan goto out; 2070e94d4478SAnirudh Venkataramanan if (set) { 2071e94d4478SAnirudh Venkataramanan u16 index = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 2072e94d4478SAnirudh Venkataramanan 2073e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_TX) { 20745726ca0eSAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_num = hw_vsi_id; 2075e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id = index; 2076e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_RX) { 20775726ca0eSAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_num = hw_vsi_id; 2078e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id = index; 2079e94d4478SAnirudh Venkataramanan } 2080e94d4478SAnirudh Venkataramanan } else { 2081e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_TX) { 2082e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 2083e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT; 2084e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_RX) { 2085e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 2086e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT; 2087e94d4478SAnirudh Venkataramanan } 2088e94d4478SAnirudh Venkataramanan } 2089e94d4478SAnirudh Venkataramanan 2090e94d4478SAnirudh Venkataramanan out: 2091e94d4478SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 2092e94d4478SAnirudh Venkataramanan return status; 2093e94d4478SAnirudh Venkataramanan } 2094e94d4478SAnirudh Venkataramanan 2095e94d4478SAnirudh Venkataramanan /** 20968b2c8582SAkeem G Abodunrin * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry 20978b2c8582SAkeem G Abodunrin * @hw: pointer to the hardware structure 20988b2c8582SAkeem G Abodunrin * @recp_id: lookup type for which the specified rule needs to be searched 20998b2c8582SAkeem G Abodunrin * @f_info: rule information 21008b2c8582SAkeem G Abodunrin * 21018b2c8582SAkeem G Abodunrin * Helper function to search for a unicast rule entry - this is to be used 21028b2c8582SAkeem G Abodunrin * to remove unicast MAC filter that is not shared with other VSIs on the 21038b2c8582SAkeem G Abodunrin * PF switch. 21048b2c8582SAkeem G Abodunrin * 21058b2c8582SAkeem G Abodunrin * Returns pointer to entry storing the rule if found 21068b2c8582SAkeem G Abodunrin */ 21078b2c8582SAkeem G Abodunrin static struct ice_fltr_mgmt_list_entry * 21088b2c8582SAkeem G Abodunrin ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id, 21098b2c8582SAkeem G Abodunrin struct ice_fltr_info *f_info) 21108b2c8582SAkeem G Abodunrin { 21118b2c8582SAkeem G Abodunrin struct ice_switch_info *sw = hw->switch_info; 21128b2c8582SAkeem G Abodunrin struct ice_fltr_mgmt_list_entry *list_itr; 21138b2c8582SAkeem G Abodunrin struct list_head *list_head; 21148b2c8582SAkeem G Abodunrin 21158b2c8582SAkeem G Abodunrin list_head = &sw->recp_list[recp_id].filt_rules; 21168b2c8582SAkeem G Abodunrin list_for_each_entry(list_itr, list_head, list_entry) { 21178b2c8582SAkeem G Abodunrin if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 21188b2c8582SAkeem G Abodunrin sizeof(f_info->l_data)) && 21198b2c8582SAkeem G Abodunrin f_info->fwd_id.hw_vsi_id == 21208b2c8582SAkeem G Abodunrin list_itr->fltr_info.fwd_id.hw_vsi_id && 21218b2c8582SAkeem G Abodunrin f_info->flag == list_itr->fltr_info.flag) 21228b2c8582SAkeem G Abodunrin return list_itr; 21238b2c8582SAkeem G Abodunrin } 21248b2c8582SAkeem G Abodunrin return NULL; 21258b2c8582SAkeem G Abodunrin } 21268b2c8582SAkeem G Abodunrin 21278b2c8582SAkeem G Abodunrin /** 212880d144c9SAnirudh Venkataramanan * ice_remove_mac - remove a MAC address based filter rule 2129d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 213080d144c9SAnirudh Venkataramanan * @m_list: list of MAC addresses and forwarding information 213180d144c9SAnirudh Venkataramanan * 213280d144c9SAnirudh Venkataramanan * This function removes either a MAC filter rule or a specific VSI from a 213380d144c9SAnirudh Venkataramanan * VSI list for a multicast MAC address. 213480d144c9SAnirudh Venkataramanan * 213580d144c9SAnirudh Venkataramanan * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 213680d144c9SAnirudh Venkataramanan * ice_add_mac. Caller should be aware that this call will only work if all 213780d144c9SAnirudh Venkataramanan * the entries passed into m_list were added previously. It will not attempt to 213880d144c9SAnirudh Venkataramanan * do a partial remove of entries that were found. 2139d76a60baSAnirudh Venkataramanan */ 2140ebb462dcSBruce Allan enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) 2141d76a60baSAnirudh Venkataramanan { 2142072f0c3dSDave Ertman struct ice_fltr_list_entry *list_itr, *tmp; 21438b2c8582SAkeem G Abodunrin struct mutex *rule_lock; /* Lock to protect filter rule list */ 2144d76a60baSAnirudh Venkataramanan 214580d144c9SAnirudh Venkataramanan if (!m_list) 2146d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 2147d76a60baSAnirudh Venkataramanan 21488b2c8582SAkeem G Abodunrin rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 2149072f0c3dSDave Ertman list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) { 215080d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 21518b2c8582SAkeem G Abodunrin u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; 21528b2c8582SAkeem G Abodunrin u16 vsi_handle; 215380d144c9SAnirudh Venkataramanan 215480d144c9SAnirudh Venkataramanan if (l_type != ICE_SW_LKUP_MAC) 215580d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 21568b2c8582SAkeem G Abodunrin 21578b2c8582SAkeem G Abodunrin vsi_handle = list_itr->fltr_info.vsi_handle; 21588b2c8582SAkeem G Abodunrin if (!ice_is_vsi_valid(hw, vsi_handle)) 21598b2c8582SAkeem G Abodunrin return ICE_ERR_PARAM; 21608b2c8582SAkeem G Abodunrin 21618b2c8582SAkeem G Abodunrin list_itr->fltr_info.fwd_id.hw_vsi_id = 21628b2c8582SAkeem G Abodunrin ice_get_hw_vsi_num(hw, vsi_handle); 21638b2c8582SAkeem G Abodunrin if (is_unicast_ether_addr(add) && !hw->ucast_shared) { 21648b2c8582SAkeem G Abodunrin /* Don't remove the unicast address that belongs to 21658b2c8582SAkeem G Abodunrin * another VSI on the switch, since it is not being 21668b2c8582SAkeem G Abodunrin * shared... 21678b2c8582SAkeem G Abodunrin */ 21688b2c8582SAkeem G Abodunrin mutex_lock(rule_lock); 21698b2c8582SAkeem G Abodunrin if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC, 21708b2c8582SAkeem G Abodunrin &list_itr->fltr_info)) { 21718b2c8582SAkeem G Abodunrin mutex_unlock(rule_lock); 21728b2c8582SAkeem G Abodunrin return ICE_ERR_DOES_NOT_EXIST; 21738b2c8582SAkeem G Abodunrin } 21748b2c8582SAkeem G Abodunrin mutex_unlock(rule_lock); 21758b2c8582SAkeem G Abodunrin } 217680d144c9SAnirudh Venkataramanan list_itr->status = ice_remove_rule_internal(hw, 217780d144c9SAnirudh Venkataramanan ICE_SW_LKUP_MAC, 217880d144c9SAnirudh Venkataramanan list_itr); 217980d144c9SAnirudh Venkataramanan if (list_itr->status) 218080d144c9SAnirudh Venkataramanan return list_itr->status; 218180d144c9SAnirudh Venkataramanan } 218280d144c9SAnirudh Venkataramanan return 0; 2183d76a60baSAnirudh Venkataramanan } 2184d76a60baSAnirudh Venkataramanan 2185d76a60baSAnirudh Venkataramanan /** 2186d76a60baSAnirudh Venkataramanan * ice_remove_vlan - Remove VLAN based filter rule 2187d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 2188d76a60baSAnirudh Venkataramanan * @v_list: list of VLAN entries and forwarding information 2189d76a60baSAnirudh Venkataramanan */ 2190d76a60baSAnirudh Venkataramanan enum ice_status 2191d76a60baSAnirudh Venkataramanan ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list) 2192d76a60baSAnirudh Venkataramanan { 2193072f0c3dSDave Ertman struct ice_fltr_list_entry *v_list_itr, *tmp; 2194d76a60baSAnirudh Venkataramanan 2195d76a60baSAnirudh Venkataramanan if (!v_list || !hw) 2196d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 2197d76a60baSAnirudh Venkataramanan 2198072f0c3dSDave Ertman list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) { 219980d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 220080d144c9SAnirudh Venkataramanan 220180d144c9SAnirudh Venkataramanan if (l_type != ICE_SW_LKUP_VLAN) 220280d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 220380d144c9SAnirudh Venkataramanan v_list_itr->status = ice_remove_rule_internal(hw, 220480d144c9SAnirudh Venkataramanan ICE_SW_LKUP_VLAN, 220580d144c9SAnirudh Venkataramanan v_list_itr); 220680d144c9SAnirudh Venkataramanan if (v_list_itr->status) 220780d144c9SAnirudh Venkataramanan return v_list_itr->status; 2208d76a60baSAnirudh Venkataramanan } 220980d144c9SAnirudh Venkataramanan return 0; 2210d76a60baSAnirudh Venkataramanan } 221180d144c9SAnirudh Venkataramanan 221280d144c9SAnirudh Venkataramanan /** 221380d144c9SAnirudh Venkataramanan * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 221480d144c9SAnirudh Venkataramanan * @fm_entry: filter entry to inspect 22155726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to compare with filter info 221680d144c9SAnirudh Venkataramanan */ 221780d144c9SAnirudh Venkataramanan static bool 22185726ca0eSAnirudh Venkataramanan ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 221980d144c9SAnirudh Venkataramanan { 222080d144c9SAnirudh Venkataramanan return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 22215726ca0eSAnirudh Venkataramanan fm_entry->fltr_info.vsi_handle == vsi_handle) || 222280d144c9SAnirudh Venkataramanan (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 22235726ca0eSAnirudh Venkataramanan (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map)))); 222480d144c9SAnirudh Venkataramanan } 222580d144c9SAnirudh Venkataramanan 222680d144c9SAnirudh Venkataramanan /** 222780d144c9SAnirudh Venkataramanan * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 222880d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 22295726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 223080d144c9SAnirudh Venkataramanan * @vsi_list_head: pointer to the list to add entry to 223180d144c9SAnirudh Venkataramanan * @fi: pointer to fltr_info of filter entry to copy & add 223280d144c9SAnirudh Venkataramanan * 223380d144c9SAnirudh Venkataramanan * Helper function, used when creating a list of filters to remove from 223480d144c9SAnirudh Venkataramanan * a specific VSI. The entry added to vsi_list_head is a COPY of the 223580d144c9SAnirudh Venkataramanan * original filter entry, with the exception of fltr_info.fltr_act and 223680d144c9SAnirudh Venkataramanan * fltr_info.fwd_id fields. These are set such that later logic can 223780d144c9SAnirudh Venkataramanan * extract which VSI to remove the fltr from, and pass on that information. 223880d144c9SAnirudh Venkataramanan */ 223980d144c9SAnirudh Venkataramanan static enum ice_status 22405726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 224180d144c9SAnirudh Venkataramanan struct list_head *vsi_list_head, 224280d144c9SAnirudh Venkataramanan struct ice_fltr_info *fi) 224380d144c9SAnirudh Venkataramanan { 224480d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 224580d144c9SAnirudh Venkataramanan 224680d144c9SAnirudh Venkataramanan /* this memory is freed up in the caller function 224780d144c9SAnirudh Venkataramanan * once filters for this VSI are removed 224880d144c9SAnirudh Venkataramanan */ 224980d144c9SAnirudh Venkataramanan tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL); 225080d144c9SAnirudh Venkataramanan if (!tmp) 225180d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 225280d144c9SAnirudh Venkataramanan 225380d144c9SAnirudh Venkataramanan tmp->fltr_info = *fi; 225480d144c9SAnirudh Venkataramanan 225580d144c9SAnirudh Venkataramanan /* Overwrite these fields to indicate which VSI to remove filter from, 225680d144c9SAnirudh Venkataramanan * so find and remove logic can extract the information from the 225780d144c9SAnirudh Venkataramanan * list entries. Note that original entries will still have proper 225880d144c9SAnirudh Venkataramanan * values. 225980d144c9SAnirudh Venkataramanan */ 226080d144c9SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 22615726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi_handle; 22625726ca0eSAnirudh Venkataramanan tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 226380d144c9SAnirudh Venkataramanan 226480d144c9SAnirudh Venkataramanan list_add(&tmp->list_entry, vsi_list_head); 226580d144c9SAnirudh Venkataramanan 226680d144c9SAnirudh Venkataramanan return 0; 2267d76a60baSAnirudh Venkataramanan } 2268d76a60baSAnirudh Venkataramanan 2269d76a60baSAnirudh Venkataramanan /** 22709daf8208SAnirudh Venkataramanan * ice_add_to_vsi_fltr_list - Add VSI filters to the list 22719daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 22725726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 22739daf8208SAnirudh Venkataramanan * @lkup_list_head: pointer to the list that has certain lookup type filters 22745726ca0eSAnirudh Venkataramanan * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 227580d144c9SAnirudh Venkataramanan * 227680d144c9SAnirudh Venkataramanan * Locates all filters in lkup_list_head that are used by the given VSI, 227780d144c9SAnirudh Venkataramanan * and adds COPIES of those entries to vsi_list_head (intended to be used 227880d144c9SAnirudh Venkataramanan * to remove the listed filters). 227980d144c9SAnirudh Venkataramanan * Note that this means all entries in vsi_list_head must be explicitly 228080d144c9SAnirudh Venkataramanan * deallocated by the caller when done with list. 22819daf8208SAnirudh Venkataramanan */ 22829daf8208SAnirudh Venkataramanan static enum ice_status 22835726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 22849daf8208SAnirudh Venkataramanan struct list_head *lkup_list_head, 22859daf8208SAnirudh Venkataramanan struct list_head *vsi_list_head) 22869daf8208SAnirudh Venkataramanan { 22879daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 228880d144c9SAnirudh Venkataramanan enum ice_status status = 0; 22899daf8208SAnirudh Venkataramanan 2290f9867df6SAnirudh Venkataramanan /* check to make sure VSI ID is valid and within boundary */ 22915726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 22929daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 22939daf8208SAnirudh Venkataramanan 22949daf8208SAnirudh Venkataramanan list_for_each_entry(fm_entry, lkup_list_head, list_entry) { 22959daf8208SAnirudh Venkataramanan struct ice_fltr_info *fi; 22969daf8208SAnirudh Venkataramanan 22979daf8208SAnirudh Venkataramanan fi = &fm_entry->fltr_info; 2298072f0c3dSDave Ertman if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) 229980d144c9SAnirudh Venkataramanan continue; 23009daf8208SAnirudh Venkataramanan 23015726ca0eSAnirudh Venkataramanan status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 230280d144c9SAnirudh Venkataramanan vsi_list_head, fi); 230380d144c9SAnirudh Venkataramanan if (status) 230480d144c9SAnirudh Venkataramanan return status; 23059daf8208SAnirudh Venkataramanan } 230680d144c9SAnirudh Venkataramanan return status; 23079daf8208SAnirudh Venkataramanan } 23089daf8208SAnirudh Venkataramanan 23099daf8208SAnirudh Venkataramanan /** 23105eda8afdSAkeem G Abodunrin * ice_determine_promisc_mask 23115eda8afdSAkeem G Abodunrin * @fi: filter info to parse 23125eda8afdSAkeem G Abodunrin * 23135eda8afdSAkeem G Abodunrin * Helper function to determine which ICE_PROMISC_ mask corresponds 23145eda8afdSAkeem G Abodunrin * to given filter into. 23155eda8afdSAkeem G Abodunrin */ 23165eda8afdSAkeem G Abodunrin static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi) 23175eda8afdSAkeem G Abodunrin { 23185eda8afdSAkeem G Abodunrin u16 vid = fi->l_data.mac_vlan.vlan_id; 23195eda8afdSAkeem G Abodunrin u8 *macaddr = fi->l_data.mac.mac_addr; 23205eda8afdSAkeem G Abodunrin bool is_tx_fltr = false; 23215eda8afdSAkeem G Abodunrin u8 promisc_mask = 0; 23225eda8afdSAkeem G Abodunrin 23235eda8afdSAkeem G Abodunrin if (fi->flag == ICE_FLTR_TX) 23245eda8afdSAkeem G Abodunrin is_tx_fltr = true; 23255eda8afdSAkeem G Abodunrin 23265eda8afdSAkeem G Abodunrin if (is_broadcast_ether_addr(macaddr)) 23275eda8afdSAkeem G Abodunrin promisc_mask |= is_tx_fltr ? 23285eda8afdSAkeem G Abodunrin ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX; 23295eda8afdSAkeem G Abodunrin else if (is_multicast_ether_addr(macaddr)) 23305eda8afdSAkeem G Abodunrin promisc_mask |= is_tx_fltr ? 23315eda8afdSAkeem G Abodunrin ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX; 23325eda8afdSAkeem G Abodunrin else if (is_unicast_ether_addr(macaddr)) 23335eda8afdSAkeem G Abodunrin promisc_mask |= is_tx_fltr ? 23345eda8afdSAkeem G Abodunrin ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX; 23355eda8afdSAkeem G Abodunrin if (vid) 23365eda8afdSAkeem G Abodunrin promisc_mask |= is_tx_fltr ? 23375eda8afdSAkeem G Abodunrin ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX; 23385eda8afdSAkeem G Abodunrin 23395eda8afdSAkeem G Abodunrin return promisc_mask; 23405eda8afdSAkeem G Abodunrin } 23415eda8afdSAkeem G Abodunrin 23425eda8afdSAkeem G Abodunrin /** 23435eda8afdSAkeem G Abodunrin * ice_remove_promisc - Remove promisc based filter rules 23445eda8afdSAkeem G Abodunrin * @hw: pointer to the hardware structure 2345f9867df6SAnirudh Venkataramanan * @recp_id: recipe ID for which the rule needs to removed 23465eda8afdSAkeem G Abodunrin * @v_list: list of promisc entries 23475eda8afdSAkeem G Abodunrin */ 23485eda8afdSAkeem G Abodunrin static enum ice_status 23495eda8afdSAkeem G Abodunrin ice_remove_promisc(struct ice_hw *hw, u8 recp_id, 23505eda8afdSAkeem G Abodunrin struct list_head *v_list) 23515eda8afdSAkeem G Abodunrin { 23525eda8afdSAkeem G Abodunrin struct ice_fltr_list_entry *v_list_itr, *tmp; 23535eda8afdSAkeem G Abodunrin 23545eda8afdSAkeem G Abodunrin list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) { 23555eda8afdSAkeem G Abodunrin v_list_itr->status = 23565eda8afdSAkeem G Abodunrin ice_remove_rule_internal(hw, recp_id, v_list_itr); 23575eda8afdSAkeem G Abodunrin if (v_list_itr->status) 23585eda8afdSAkeem G Abodunrin return v_list_itr->status; 23595eda8afdSAkeem G Abodunrin } 23605eda8afdSAkeem G Abodunrin return 0; 23615eda8afdSAkeem G Abodunrin } 23625eda8afdSAkeem G Abodunrin 23635eda8afdSAkeem G Abodunrin /** 23645eda8afdSAkeem G Abodunrin * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 23655eda8afdSAkeem G Abodunrin * @hw: pointer to the hardware structure 23665eda8afdSAkeem G Abodunrin * @vsi_handle: VSI handle to clear mode 23675eda8afdSAkeem G Abodunrin * @promisc_mask: mask of promiscuous config bits to clear 23685eda8afdSAkeem G Abodunrin * @vid: VLAN ID to clear VLAN promiscuous 23695eda8afdSAkeem G Abodunrin */ 23705eda8afdSAkeem G Abodunrin enum ice_status 23715eda8afdSAkeem G Abodunrin ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 23725eda8afdSAkeem G Abodunrin u16 vid) 23735eda8afdSAkeem G Abodunrin { 23745eda8afdSAkeem G Abodunrin struct ice_switch_info *sw = hw->switch_info; 23755eda8afdSAkeem G Abodunrin struct ice_fltr_list_entry *fm_entry, *tmp; 23765eda8afdSAkeem G Abodunrin struct list_head remove_list_head; 23775eda8afdSAkeem G Abodunrin struct ice_fltr_mgmt_list_entry *itr; 23785eda8afdSAkeem G Abodunrin struct list_head *rule_head; 23795eda8afdSAkeem G Abodunrin struct mutex *rule_lock; /* Lock to protect filter rule list */ 23805eda8afdSAkeem G Abodunrin enum ice_status status = 0; 23815eda8afdSAkeem G Abodunrin u8 recipe_id; 23825eda8afdSAkeem G Abodunrin 23835eda8afdSAkeem G Abodunrin if (!ice_is_vsi_valid(hw, vsi_handle)) 23845eda8afdSAkeem G Abodunrin return ICE_ERR_PARAM; 23855eda8afdSAkeem G Abodunrin 23861bc7a4abSBrett Creeley if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) 23875eda8afdSAkeem G Abodunrin recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 23885eda8afdSAkeem G Abodunrin else 23895eda8afdSAkeem G Abodunrin recipe_id = ICE_SW_LKUP_PROMISC; 23905eda8afdSAkeem G Abodunrin 23915eda8afdSAkeem G Abodunrin rule_head = &sw->recp_list[recipe_id].filt_rules; 23925eda8afdSAkeem G Abodunrin rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 23935eda8afdSAkeem G Abodunrin 23945eda8afdSAkeem G Abodunrin INIT_LIST_HEAD(&remove_list_head); 23955eda8afdSAkeem G Abodunrin 23965eda8afdSAkeem G Abodunrin mutex_lock(rule_lock); 23975eda8afdSAkeem G Abodunrin list_for_each_entry(itr, rule_head, list_entry) { 23981bc7a4abSBrett Creeley struct ice_fltr_info *fltr_info; 23995eda8afdSAkeem G Abodunrin u8 fltr_promisc_mask = 0; 24005eda8afdSAkeem G Abodunrin 24015eda8afdSAkeem G Abodunrin if (!ice_vsi_uses_fltr(itr, vsi_handle)) 24025eda8afdSAkeem G Abodunrin continue; 24031bc7a4abSBrett Creeley fltr_info = &itr->fltr_info; 24045eda8afdSAkeem G Abodunrin 24051bc7a4abSBrett Creeley if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN && 24061bc7a4abSBrett Creeley vid != fltr_info->l_data.mac_vlan.vlan_id) 24071bc7a4abSBrett Creeley continue; 24081bc7a4abSBrett Creeley 24091bc7a4abSBrett Creeley fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info); 24105eda8afdSAkeem G Abodunrin 24115eda8afdSAkeem G Abodunrin /* Skip if filter is not completely specified by given mask */ 24125eda8afdSAkeem G Abodunrin if (fltr_promisc_mask & ~promisc_mask) 24135eda8afdSAkeem G Abodunrin continue; 24145eda8afdSAkeem G Abodunrin 24155eda8afdSAkeem G Abodunrin status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 24165eda8afdSAkeem G Abodunrin &remove_list_head, 24171bc7a4abSBrett Creeley fltr_info); 24185eda8afdSAkeem G Abodunrin if (status) { 24195eda8afdSAkeem G Abodunrin mutex_unlock(rule_lock); 24205eda8afdSAkeem G Abodunrin goto free_fltr_list; 24215eda8afdSAkeem G Abodunrin } 24225eda8afdSAkeem G Abodunrin } 24235eda8afdSAkeem G Abodunrin mutex_unlock(rule_lock); 24245eda8afdSAkeem G Abodunrin 24255eda8afdSAkeem G Abodunrin status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 24265eda8afdSAkeem G Abodunrin 24275eda8afdSAkeem G Abodunrin free_fltr_list: 24285eda8afdSAkeem G Abodunrin list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { 24295eda8afdSAkeem G Abodunrin list_del(&fm_entry->list_entry); 24305eda8afdSAkeem G Abodunrin devm_kfree(ice_hw_to_dev(hw), fm_entry); 24315eda8afdSAkeem G Abodunrin } 24325eda8afdSAkeem G Abodunrin 24335eda8afdSAkeem G Abodunrin return status; 24345eda8afdSAkeem G Abodunrin } 24355eda8afdSAkeem G Abodunrin 24365eda8afdSAkeem G Abodunrin /** 24375eda8afdSAkeem G Abodunrin * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 24385eda8afdSAkeem G Abodunrin * @hw: pointer to the hardware structure 24395eda8afdSAkeem G Abodunrin * @vsi_handle: VSI handle to configure 24405eda8afdSAkeem G Abodunrin * @promisc_mask: mask of promiscuous config bits 24415eda8afdSAkeem G Abodunrin * @vid: VLAN ID to set VLAN promiscuous 24425eda8afdSAkeem G Abodunrin */ 24435eda8afdSAkeem G Abodunrin enum ice_status 24445eda8afdSAkeem G Abodunrin ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid) 24455eda8afdSAkeem G Abodunrin { 24465eda8afdSAkeem G Abodunrin enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 24475eda8afdSAkeem G Abodunrin struct ice_fltr_list_entry f_list_entry; 24485eda8afdSAkeem G Abodunrin struct ice_fltr_info new_fltr; 24495eda8afdSAkeem G Abodunrin enum ice_status status = 0; 24505eda8afdSAkeem G Abodunrin bool is_tx_fltr; 24515eda8afdSAkeem G Abodunrin u16 hw_vsi_id; 24525eda8afdSAkeem G Abodunrin int pkt_type; 24535eda8afdSAkeem G Abodunrin u8 recipe_id; 24545eda8afdSAkeem G Abodunrin 24555eda8afdSAkeem G Abodunrin if (!ice_is_vsi_valid(hw, vsi_handle)) 24565eda8afdSAkeem G Abodunrin return ICE_ERR_PARAM; 24575eda8afdSAkeem G Abodunrin hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 24585eda8afdSAkeem G Abodunrin 24595eda8afdSAkeem G Abodunrin memset(&new_fltr, 0, sizeof(new_fltr)); 24605eda8afdSAkeem G Abodunrin 24615eda8afdSAkeem G Abodunrin if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) { 24625eda8afdSAkeem G Abodunrin new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 24635eda8afdSAkeem G Abodunrin new_fltr.l_data.mac_vlan.vlan_id = vid; 24645eda8afdSAkeem G Abodunrin recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 24655eda8afdSAkeem G Abodunrin } else { 24665eda8afdSAkeem G Abodunrin new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 24675eda8afdSAkeem G Abodunrin recipe_id = ICE_SW_LKUP_PROMISC; 24685eda8afdSAkeem G Abodunrin } 24695eda8afdSAkeem G Abodunrin 24705eda8afdSAkeem G Abodunrin /* Separate filters must be set for each direction/packet type 24715eda8afdSAkeem G Abodunrin * combination, so we will loop over the mask value, store the 24725eda8afdSAkeem G Abodunrin * individual type, and clear it out in the input mask as it 24735eda8afdSAkeem G Abodunrin * is found. 24745eda8afdSAkeem G Abodunrin */ 24755eda8afdSAkeem G Abodunrin while (promisc_mask) { 24765eda8afdSAkeem G Abodunrin u8 *mac_addr; 24775eda8afdSAkeem G Abodunrin 24785eda8afdSAkeem G Abodunrin pkt_type = 0; 24795eda8afdSAkeem G Abodunrin is_tx_fltr = false; 24805eda8afdSAkeem G Abodunrin 24815eda8afdSAkeem G Abodunrin if (promisc_mask & ICE_PROMISC_UCAST_RX) { 24825eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_UCAST_RX; 24835eda8afdSAkeem G Abodunrin pkt_type = UCAST_FLTR; 24845eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_UCAST_TX) { 24855eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_UCAST_TX; 24865eda8afdSAkeem G Abodunrin pkt_type = UCAST_FLTR; 24875eda8afdSAkeem G Abodunrin is_tx_fltr = true; 24885eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_MCAST_RX) { 24895eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_MCAST_RX; 24905eda8afdSAkeem G Abodunrin pkt_type = MCAST_FLTR; 24915eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_MCAST_TX) { 24925eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_MCAST_TX; 24935eda8afdSAkeem G Abodunrin pkt_type = MCAST_FLTR; 24945eda8afdSAkeem G Abodunrin is_tx_fltr = true; 24955eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_BCAST_RX) { 24965eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_BCAST_RX; 24975eda8afdSAkeem G Abodunrin pkt_type = BCAST_FLTR; 24985eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_BCAST_TX) { 24995eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_BCAST_TX; 25005eda8afdSAkeem G Abodunrin pkt_type = BCAST_FLTR; 25015eda8afdSAkeem G Abodunrin is_tx_fltr = true; 25025eda8afdSAkeem G Abodunrin } 25035eda8afdSAkeem G Abodunrin 25045eda8afdSAkeem G Abodunrin /* Check for VLAN promiscuous flag */ 25055eda8afdSAkeem G Abodunrin if (promisc_mask & ICE_PROMISC_VLAN_RX) { 25065eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_VLAN_RX; 25075eda8afdSAkeem G Abodunrin } else if (promisc_mask & ICE_PROMISC_VLAN_TX) { 25085eda8afdSAkeem G Abodunrin promisc_mask &= ~ICE_PROMISC_VLAN_TX; 25095eda8afdSAkeem G Abodunrin is_tx_fltr = true; 25105eda8afdSAkeem G Abodunrin } 25115eda8afdSAkeem G Abodunrin 25125eda8afdSAkeem G Abodunrin /* Set filter DA based on packet type */ 25135eda8afdSAkeem G Abodunrin mac_addr = new_fltr.l_data.mac.mac_addr; 25145eda8afdSAkeem G Abodunrin if (pkt_type == BCAST_FLTR) { 25155eda8afdSAkeem G Abodunrin eth_broadcast_addr(mac_addr); 25165eda8afdSAkeem G Abodunrin } else if (pkt_type == MCAST_FLTR || 25175eda8afdSAkeem G Abodunrin pkt_type == UCAST_FLTR) { 25185eda8afdSAkeem G Abodunrin /* Use the dummy ether header DA */ 25195eda8afdSAkeem G Abodunrin ether_addr_copy(mac_addr, dummy_eth_header); 25205eda8afdSAkeem G Abodunrin if (pkt_type == MCAST_FLTR) 25215eda8afdSAkeem G Abodunrin mac_addr[0] |= 0x1; /* Set multicast bit */ 25225eda8afdSAkeem G Abodunrin } 25235eda8afdSAkeem G Abodunrin 25245eda8afdSAkeem G Abodunrin /* Need to reset this to zero for all iterations */ 25255eda8afdSAkeem G Abodunrin new_fltr.flag = 0; 25265eda8afdSAkeem G Abodunrin if (is_tx_fltr) { 25275eda8afdSAkeem G Abodunrin new_fltr.flag |= ICE_FLTR_TX; 25285eda8afdSAkeem G Abodunrin new_fltr.src = hw_vsi_id; 25295eda8afdSAkeem G Abodunrin } else { 25305eda8afdSAkeem G Abodunrin new_fltr.flag |= ICE_FLTR_RX; 25315eda8afdSAkeem G Abodunrin new_fltr.src = hw->port_info->lport; 25325eda8afdSAkeem G Abodunrin } 25335eda8afdSAkeem G Abodunrin 25345eda8afdSAkeem G Abodunrin new_fltr.fltr_act = ICE_FWD_TO_VSI; 25355eda8afdSAkeem G Abodunrin new_fltr.vsi_handle = vsi_handle; 25365eda8afdSAkeem G Abodunrin new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 25375eda8afdSAkeem G Abodunrin f_list_entry.fltr_info = new_fltr; 25385eda8afdSAkeem G Abodunrin 25395eda8afdSAkeem G Abodunrin status = ice_add_rule_internal(hw, recipe_id, &f_list_entry); 25405eda8afdSAkeem G Abodunrin if (status) 25415eda8afdSAkeem G Abodunrin goto set_promisc_exit; 25425eda8afdSAkeem G Abodunrin } 25435eda8afdSAkeem G Abodunrin 25445eda8afdSAkeem G Abodunrin set_promisc_exit: 25455eda8afdSAkeem G Abodunrin return status; 25465eda8afdSAkeem G Abodunrin } 25475eda8afdSAkeem G Abodunrin 25485eda8afdSAkeem G Abodunrin /** 25495eda8afdSAkeem G Abodunrin * ice_set_vlan_vsi_promisc 25505eda8afdSAkeem G Abodunrin * @hw: pointer to the hardware structure 25515eda8afdSAkeem G Abodunrin * @vsi_handle: VSI handle to configure 25525eda8afdSAkeem G Abodunrin * @promisc_mask: mask of promiscuous config bits 25535eda8afdSAkeem G Abodunrin * @rm_vlan_promisc: Clear VLANs VSI promisc mode 25545eda8afdSAkeem G Abodunrin * 25555eda8afdSAkeem G Abodunrin * Configure VSI with all associated VLANs to given promiscuous mode(s) 25565eda8afdSAkeem G Abodunrin */ 25575eda8afdSAkeem G Abodunrin enum ice_status 25585eda8afdSAkeem G Abodunrin ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 25595eda8afdSAkeem G Abodunrin bool rm_vlan_promisc) 25605eda8afdSAkeem G Abodunrin { 25615eda8afdSAkeem G Abodunrin struct ice_switch_info *sw = hw->switch_info; 25625eda8afdSAkeem G Abodunrin struct ice_fltr_list_entry *list_itr, *tmp; 25635eda8afdSAkeem G Abodunrin struct list_head vsi_list_head; 25645eda8afdSAkeem G Abodunrin struct list_head *vlan_head; 25655eda8afdSAkeem G Abodunrin struct mutex *vlan_lock; /* Lock to protect filter rule list */ 25665eda8afdSAkeem G Abodunrin enum ice_status status; 25675eda8afdSAkeem G Abodunrin u16 vlan_id; 25685eda8afdSAkeem G Abodunrin 25695eda8afdSAkeem G Abodunrin INIT_LIST_HEAD(&vsi_list_head); 25705eda8afdSAkeem G Abodunrin vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 25715eda8afdSAkeem G Abodunrin vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 25725eda8afdSAkeem G Abodunrin mutex_lock(vlan_lock); 25735eda8afdSAkeem G Abodunrin status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 25745eda8afdSAkeem G Abodunrin &vsi_list_head); 25755eda8afdSAkeem G Abodunrin mutex_unlock(vlan_lock); 25765eda8afdSAkeem G Abodunrin if (status) 25775eda8afdSAkeem G Abodunrin goto free_fltr_list; 25785eda8afdSAkeem G Abodunrin 25795eda8afdSAkeem G Abodunrin list_for_each_entry(list_itr, &vsi_list_head, list_entry) { 25805eda8afdSAkeem G Abodunrin vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 25815eda8afdSAkeem G Abodunrin if (rm_vlan_promisc) 25825eda8afdSAkeem G Abodunrin status = ice_clear_vsi_promisc(hw, vsi_handle, 25835eda8afdSAkeem G Abodunrin promisc_mask, vlan_id); 25845eda8afdSAkeem G Abodunrin else 25855eda8afdSAkeem G Abodunrin status = ice_set_vsi_promisc(hw, vsi_handle, 25865eda8afdSAkeem G Abodunrin promisc_mask, vlan_id); 25875eda8afdSAkeem G Abodunrin if (status) 25885eda8afdSAkeem G Abodunrin break; 25895eda8afdSAkeem G Abodunrin } 25905eda8afdSAkeem G Abodunrin 25915eda8afdSAkeem G Abodunrin free_fltr_list: 25925eda8afdSAkeem G Abodunrin list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) { 25935eda8afdSAkeem G Abodunrin list_del(&list_itr->list_entry); 25945eda8afdSAkeem G Abodunrin devm_kfree(ice_hw_to_dev(hw), list_itr); 25955eda8afdSAkeem G Abodunrin } 25965eda8afdSAkeem G Abodunrin return status; 25975eda8afdSAkeem G Abodunrin } 25985eda8afdSAkeem G Abodunrin 25995eda8afdSAkeem G Abodunrin /** 26009daf8208SAnirudh Venkataramanan * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 26019daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 26025726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 26039daf8208SAnirudh Venkataramanan * @lkup: switch rule filter lookup type 26049daf8208SAnirudh Venkataramanan */ 26059daf8208SAnirudh Venkataramanan static void 26065726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 26079daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup) 26089daf8208SAnirudh Venkataramanan { 26099daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 26109daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *fm_entry; 26119daf8208SAnirudh Venkataramanan struct list_head remove_list_head; 261280d144c9SAnirudh Venkataramanan struct list_head *rule_head; 26139daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 261480d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 26159daf8208SAnirudh Venkataramanan enum ice_status status; 26169daf8208SAnirudh Venkataramanan 26179daf8208SAnirudh Venkataramanan INIT_LIST_HEAD(&remove_list_head); 261880d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[lkup].filt_rule_lock; 261980d144c9SAnirudh Venkataramanan rule_head = &sw->recp_list[lkup].filt_rules; 262080d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 26215726ca0eSAnirudh Venkataramanan status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 262280d144c9SAnirudh Venkataramanan &remove_list_head); 262380d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 262480d144c9SAnirudh Venkataramanan if (status) 262580d144c9SAnirudh Venkataramanan return; 262680d144c9SAnirudh Venkataramanan 26279daf8208SAnirudh Venkataramanan switch (lkup) { 26289daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC: 26299daf8208SAnirudh Venkataramanan ice_remove_mac(hw, &remove_list_head); 26309daf8208SAnirudh Venkataramanan break; 26319daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_VLAN: 2632d76a60baSAnirudh Venkataramanan ice_remove_vlan(hw, &remove_list_head); 2633d76a60baSAnirudh Venkataramanan break; 26345eda8afdSAkeem G Abodunrin case ICE_SW_LKUP_PROMISC: 26355eda8afdSAkeem G Abodunrin case ICE_SW_LKUP_PROMISC_VLAN: 26365eda8afdSAkeem G Abodunrin ice_remove_promisc(hw, lkup, &remove_list_head); 26375eda8afdSAkeem G Abodunrin break; 26389daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC_VLAN: 26399daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE: 26409daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE_MAC: 26419daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_DFLT: 264280d144c9SAnirudh Venkataramanan case ICE_SW_LKUP_LAST: 264380d144c9SAnirudh Venkataramanan default: 264480d144c9SAnirudh Venkataramanan ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup); 26459daf8208SAnirudh Venkataramanan break; 26469daf8208SAnirudh Venkataramanan } 26479daf8208SAnirudh Venkataramanan 26489daf8208SAnirudh Venkataramanan list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { 26499daf8208SAnirudh Venkataramanan list_del(&fm_entry->list_entry); 26509daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), fm_entry); 26519daf8208SAnirudh Venkataramanan } 26529daf8208SAnirudh Venkataramanan } 26539daf8208SAnirudh Venkataramanan 26549daf8208SAnirudh Venkataramanan /** 26559daf8208SAnirudh Venkataramanan * ice_remove_vsi_fltr - Remove all filters for a VSI 26569daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 26575726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 26589daf8208SAnirudh Venkataramanan */ 26595726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 26609daf8208SAnirudh Venkataramanan { 26615726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC); 26625726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN); 26635726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC); 26645726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN); 26655726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT); 26665726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE); 26675726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC); 26685726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN); 26699daf8208SAnirudh Venkataramanan } 26700f9d5027SAnirudh Venkataramanan 26710f9d5027SAnirudh Venkataramanan /** 2672148beb61SHenry Tieman * ice_alloc_res_cntr - allocating resource counter 2673148beb61SHenry Tieman * @hw: pointer to the hardware structure 2674148beb61SHenry Tieman * @type: type of resource 2675148beb61SHenry Tieman * @alloc_shared: if set it is shared else dedicated 2676148beb61SHenry Tieman * @num_items: number of entries requested for FD resource type 2677148beb61SHenry Tieman * @counter_id: counter index returned by AQ call 2678148beb61SHenry Tieman */ 2679148beb61SHenry Tieman enum ice_status 2680148beb61SHenry Tieman ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 2681148beb61SHenry Tieman u16 *counter_id) 2682148beb61SHenry Tieman { 2683148beb61SHenry Tieman struct ice_aqc_alloc_free_res_elem *buf; 2684148beb61SHenry Tieman enum ice_status status; 2685148beb61SHenry Tieman u16 buf_len; 2686148beb61SHenry Tieman 2687148beb61SHenry Tieman /* Allocate resource */ 268866486d89SBruce Allan buf_len = struct_size(buf, elem, 1); 2689148beb61SHenry Tieman buf = kzalloc(buf_len, GFP_KERNEL); 2690148beb61SHenry Tieman if (!buf) 2691148beb61SHenry Tieman return ICE_ERR_NO_MEMORY; 2692148beb61SHenry Tieman 2693148beb61SHenry Tieman buf->num_elems = cpu_to_le16(num_items); 2694148beb61SHenry Tieman buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 2695148beb61SHenry Tieman ICE_AQC_RES_TYPE_M) | alloc_shared); 2696148beb61SHenry Tieman 2697148beb61SHenry Tieman status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 2698148beb61SHenry Tieman ice_aqc_opc_alloc_res, NULL); 2699148beb61SHenry Tieman if (status) 2700148beb61SHenry Tieman goto exit; 2701148beb61SHenry Tieman 2702148beb61SHenry Tieman *counter_id = le16_to_cpu(buf->elem[0].e.sw_resp); 2703148beb61SHenry Tieman 2704148beb61SHenry Tieman exit: 2705148beb61SHenry Tieman kfree(buf); 2706148beb61SHenry Tieman return status; 2707148beb61SHenry Tieman } 2708148beb61SHenry Tieman 2709148beb61SHenry Tieman /** 2710148beb61SHenry Tieman * ice_free_res_cntr - free resource counter 2711148beb61SHenry Tieman * @hw: pointer to the hardware structure 2712148beb61SHenry Tieman * @type: type of resource 2713148beb61SHenry Tieman * @alloc_shared: if set it is shared else dedicated 2714148beb61SHenry Tieman * @num_items: number of entries to be freed for FD resource type 2715148beb61SHenry Tieman * @counter_id: counter ID resource which needs to be freed 2716148beb61SHenry Tieman */ 2717148beb61SHenry Tieman enum ice_status 2718148beb61SHenry Tieman ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 2719148beb61SHenry Tieman u16 counter_id) 2720148beb61SHenry Tieman { 2721148beb61SHenry Tieman struct ice_aqc_alloc_free_res_elem *buf; 2722148beb61SHenry Tieman enum ice_status status; 2723148beb61SHenry Tieman u16 buf_len; 2724148beb61SHenry Tieman 2725148beb61SHenry Tieman /* Free resource */ 272666486d89SBruce Allan buf_len = struct_size(buf, elem, 1); 2727148beb61SHenry Tieman buf = kzalloc(buf_len, GFP_KERNEL); 2728148beb61SHenry Tieman if (!buf) 2729148beb61SHenry Tieman return ICE_ERR_NO_MEMORY; 2730148beb61SHenry Tieman 2731148beb61SHenry Tieman buf->num_elems = cpu_to_le16(num_items); 2732148beb61SHenry Tieman buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 2733148beb61SHenry Tieman ICE_AQC_RES_TYPE_M) | alloc_shared); 2734148beb61SHenry Tieman buf->elem[0].e.sw_resp = cpu_to_le16(counter_id); 2735148beb61SHenry Tieman 2736148beb61SHenry Tieman status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 2737148beb61SHenry Tieman ice_aqc_opc_free_res, NULL); 2738148beb61SHenry Tieman if (status) 27399228d8b2SJacob Keller ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n"); 2740148beb61SHenry Tieman 2741148beb61SHenry Tieman kfree(buf); 2742148beb61SHenry Tieman return status; 2743148beb61SHenry Tieman } 2744148beb61SHenry Tieman 2745148beb61SHenry Tieman /** 2746334cb062SAnirudh Venkataramanan * ice_replay_vsi_fltr - Replay filters for requested VSI 27470f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 2748334cb062SAnirudh Venkataramanan * @vsi_handle: driver VSI handle 2749f9867df6SAnirudh Venkataramanan * @recp_id: Recipe ID for which rules need to be replayed 2750334cb062SAnirudh Venkataramanan * @list_head: list for which filters need to be replayed 2751334cb062SAnirudh Venkataramanan * 2752334cb062SAnirudh Venkataramanan * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 2753334cb062SAnirudh Venkataramanan * It is required to pass valid VSI handle. 27540f9d5027SAnirudh Venkataramanan */ 27550f9d5027SAnirudh Venkataramanan static enum ice_status 2756334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id, 2757334cb062SAnirudh Venkataramanan struct list_head *list_head) 27580f9d5027SAnirudh Venkataramanan { 27590f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *itr; 27600f9d5027SAnirudh Venkataramanan enum ice_status status = 0; 2761334cb062SAnirudh Venkataramanan u16 hw_vsi_id; 27620f9d5027SAnirudh Venkataramanan 27630f9d5027SAnirudh Venkataramanan if (list_empty(list_head)) 27640f9d5027SAnirudh Venkataramanan return status; 2765334cb062SAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 27660f9d5027SAnirudh Venkataramanan 2767334cb062SAnirudh Venkataramanan list_for_each_entry(itr, list_head, list_entry) { 27680f9d5027SAnirudh Venkataramanan struct ice_fltr_list_entry f_entry; 27690f9d5027SAnirudh Venkataramanan 27700f9d5027SAnirudh Venkataramanan f_entry.fltr_info = itr->fltr_info; 2771334cb062SAnirudh Venkataramanan if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 2772334cb062SAnirudh Venkataramanan itr->fltr_info.vsi_handle == vsi_handle) { 2773f9867df6SAnirudh Venkataramanan /* update the src in case it is VSI num */ 2774334cb062SAnirudh Venkataramanan if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 2775334cb062SAnirudh Venkataramanan f_entry.fltr_info.src = hw_vsi_id; 27760f9d5027SAnirudh Venkataramanan status = ice_add_rule_internal(hw, recp_id, &f_entry); 27770f9d5027SAnirudh Venkataramanan if (status) 27780f9d5027SAnirudh Venkataramanan goto end; 27790f9d5027SAnirudh Venkataramanan continue; 27800f9d5027SAnirudh Venkataramanan } 2781072f0c3dSDave Ertman if (!itr->vsi_list_info || 2782072f0c3dSDave Ertman !test_bit(vsi_handle, itr->vsi_list_info->vsi_map)) 2783334cb062SAnirudh Venkataramanan continue; 2784334cb062SAnirudh Venkataramanan /* Clearing it so that the logic can add it back */ 2785334cb062SAnirudh Venkataramanan clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 2786334cb062SAnirudh Venkataramanan f_entry.fltr_info.vsi_handle = vsi_handle; 27870f9d5027SAnirudh Venkataramanan f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 2788f9867df6SAnirudh Venkataramanan /* update the src in case it is VSI num */ 2789334cb062SAnirudh Venkataramanan if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 2790334cb062SAnirudh Venkataramanan f_entry.fltr_info.src = hw_vsi_id; 27910f9d5027SAnirudh Venkataramanan if (recp_id == ICE_SW_LKUP_VLAN) 27920f9d5027SAnirudh Venkataramanan status = ice_add_vlan_internal(hw, &f_entry); 27930f9d5027SAnirudh Venkataramanan else 2794334cb062SAnirudh Venkataramanan status = ice_add_rule_internal(hw, recp_id, &f_entry); 27950f9d5027SAnirudh Venkataramanan if (status) 27960f9d5027SAnirudh Venkataramanan goto end; 27970f9d5027SAnirudh Venkataramanan } 27980f9d5027SAnirudh Venkataramanan end: 27990f9d5027SAnirudh Venkataramanan return status; 28000f9d5027SAnirudh Venkataramanan } 28010f9d5027SAnirudh Venkataramanan 28020f9d5027SAnirudh Venkataramanan /** 2803334cb062SAnirudh Venkataramanan * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 28040f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 2805334cb062SAnirudh Venkataramanan * @vsi_handle: driver VSI handle 28060f9d5027SAnirudh Venkataramanan * 2807334cb062SAnirudh Venkataramanan * Replays filters for requested VSI via vsi_handle. 28080f9d5027SAnirudh Venkataramanan */ 2809334cb062SAnirudh Venkataramanan enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle) 28100f9d5027SAnirudh Venkataramanan { 28110f9d5027SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 28120f9d5027SAnirudh Venkataramanan enum ice_status status = 0; 28130f9d5027SAnirudh Venkataramanan u8 i; 28140f9d5027SAnirudh Venkataramanan 28150f9d5027SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 2816334cb062SAnirudh Venkataramanan struct list_head *head; 28170f9d5027SAnirudh Venkataramanan 2818334cb062SAnirudh Venkataramanan head = &sw->recp_list[i].filt_replay_rules; 2819334cb062SAnirudh Venkataramanan status = ice_replay_vsi_fltr(hw, vsi_handle, i, head); 28200f9d5027SAnirudh Venkataramanan if (status) 28210f9d5027SAnirudh Venkataramanan return status; 28220f9d5027SAnirudh Venkataramanan } 28230f9d5027SAnirudh Venkataramanan return status; 28240f9d5027SAnirudh Venkataramanan } 2825334cb062SAnirudh Venkataramanan 2826334cb062SAnirudh Venkataramanan /** 2827334cb062SAnirudh Venkataramanan * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 2828f9867df6SAnirudh Venkataramanan * @hw: pointer to the HW struct 2829334cb062SAnirudh Venkataramanan * 2830334cb062SAnirudh Venkataramanan * Deletes the filter replay rules. 2831334cb062SAnirudh Venkataramanan */ 2832334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 2833334cb062SAnirudh Venkataramanan { 2834334cb062SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 2835334cb062SAnirudh Venkataramanan u8 i; 2836334cb062SAnirudh Venkataramanan 2837334cb062SAnirudh Venkataramanan if (!sw) 2838334cb062SAnirudh Venkataramanan return; 2839334cb062SAnirudh Venkataramanan 2840334cb062SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 2841334cb062SAnirudh Venkataramanan if (!list_empty(&sw->recp_list[i].filt_replay_rules)) { 2842334cb062SAnirudh Venkataramanan struct list_head *l_head; 2843334cb062SAnirudh Venkataramanan 2844334cb062SAnirudh Venkataramanan l_head = &sw->recp_list[i].filt_replay_rules; 2845334cb062SAnirudh Venkataramanan ice_rem_sw_rule_info(hw, l_head); 2846334cb062SAnirudh Venkataramanan } 2847334cb062SAnirudh Venkataramanan } 2848334cb062SAnirudh Venkataramanan } 2849