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) 229daf8208SAnirudh 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 \ 329daf8208SAnirudh Venkataramanan (sizeof(struct ice_aqc_sw_rules_elem) - \ 339daf8208SAnirudh Venkataramanan sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 349daf8208SAnirudh Venkataramanan sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1) 359daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \ 369daf8208SAnirudh Venkataramanan (sizeof(struct ice_aqc_sw_rules_elem) - \ 379daf8208SAnirudh Venkataramanan sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 389daf8208SAnirudh Venkataramanan sizeof(struct ice_sw_rule_lkup_rx_tx) - 1) 399daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_LG_ACT_SIZE(n) \ 409daf8208SAnirudh Venkataramanan (sizeof(struct ice_aqc_sw_rules_elem) - \ 419daf8208SAnirudh Venkataramanan sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 429daf8208SAnirudh Venkataramanan sizeof(struct ice_sw_rule_lg_act) - \ 439daf8208SAnirudh Venkataramanan sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \ 449daf8208SAnirudh Venkataramanan ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act))) 459daf8208SAnirudh Venkataramanan #define ICE_SW_RULE_VSI_LIST_SIZE(n) \ 469daf8208SAnirudh Venkataramanan (sizeof(struct ice_aqc_sw_rules_elem) - \ 479daf8208SAnirudh Venkataramanan sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 489daf8208SAnirudh Venkataramanan sizeof(struct ice_sw_rule_vsi_list) - \ 499daf8208SAnirudh Venkataramanan sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \ 509daf8208SAnirudh Venkataramanan ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi))) 519daf8208SAnirudh Venkataramanan 529daf8208SAnirudh Venkataramanan /** 539daf8208SAnirudh Venkataramanan * ice_aq_alloc_free_res - command to allocate/free resources 549daf8208SAnirudh Venkataramanan * @hw: pointer to the hw struct 559daf8208SAnirudh Venkataramanan * @num_entries: number of resource entries in buffer 569daf8208SAnirudh Venkataramanan * @buf: Indirect buffer to hold data parameters and response 579daf8208SAnirudh Venkataramanan * @buf_size: size of buffer for indirect commands 589daf8208SAnirudh Venkataramanan * @opc: pass in the command opcode 599daf8208SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 609daf8208SAnirudh Venkataramanan * 619daf8208SAnirudh Venkataramanan * Helper function to allocate/free resources using the admin queue commands 629daf8208SAnirudh Venkataramanan */ 639daf8208SAnirudh Venkataramanan static enum ice_status 649daf8208SAnirudh Venkataramanan ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, 659daf8208SAnirudh Venkataramanan struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 669daf8208SAnirudh Venkataramanan enum ice_adminq_opc opc, struct ice_sq_cd *cd) 679daf8208SAnirudh Venkataramanan { 689daf8208SAnirudh Venkataramanan struct ice_aqc_alloc_free_res_cmd *cmd; 699daf8208SAnirudh Venkataramanan struct ice_aq_desc desc; 709daf8208SAnirudh Venkataramanan 719daf8208SAnirudh Venkataramanan cmd = &desc.params.sw_res_ctrl; 729daf8208SAnirudh Venkataramanan 739daf8208SAnirudh Venkataramanan if (!buf) 749daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 759daf8208SAnirudh Venkataramanan 769daf8208SAnirudh Venkataramanan if (buf_size < (num_entries * sizeof(buf->elem[0]))) 779daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 789daf8208SAnirudh Venkataramanan 799daf8208SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, opc); 809daf8208SAnirudh Venkataramanan 819daf8208SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 829daf8208SAnirudh Venkataramanan 839daf8208SAnirudh Venkataramanan cmd->num_entries = cpu_to_le16(num_entries); 849daf8208SAnirudh Venkataramanan 859daf8208SAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 869daf8208SAnirudh Venkataramanan } 879daf8208SAnirudh Venkataramanan 889c20346bSAnirudh Venkataramanan /** 8980d144c9SAnirudh Venkataramanan * ice_init_def_sw_recp - initialize the recipe book keeping tables 9080d144c9SAnirudh Venkataramanan * @hw: pointer to the hw struct 9180d144c9SAnirudh Venkataramanan * 9280d144c9SAnirudh Venkataramanan * Allocate memory for the entire recipe table and initialize the structures/ 9380d144c9SAnirudh Venkataramanan * entries corresponding to basic recipes. 9480d144c9SAnirudh Venkataramanan */ 9580d144c9SAnirudh Venkataramanan enum ice_status 9680d144c9SAnirudh Venkataramanan ice_init_def_sw_recp(struct ice_hw *hw) 9780d144c9SAnirudh Venkataramanan { 9880d144c9SAnirudh Venkataramanan struct ice_sw_recipe *recps; 9980d144c9SAnirudh Venkataramanan u8 i; 10080d144c9SAnirudh Venkataramanan 10180d144c9SAnirudh Venkataramanan recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES, 10280d144c9SAnirudh Venkataramanan sizeof(struct ice_sw_recipe), GFP_KERNEL); 10380d144c9SAnirudh Venkataramanan if (!recps) 10480d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 10580d144c9SAnirudh Venkataramanan 10680d144c9SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 10780d144c9SAnirudh Venkataramanan recps[i].root_rid = i; 10880d144c9SAnirudh Venkataramanan INIT_LIST_HEAD(&recps[i].filt_rules); 109334cb062SAnirudh Venkataramanan INIT_LIST_HEAD(&recps[i].filt_replay_rules); 11080d144c9SAnirudh Venkataramanan mutex_init(&recps[i].filt_rule_lock); 11180d144c9SAnirudh Venkataramanan } 11280d144c9SAnirudh Venkataramanan 11380d144c9SAnirudh Venkataramanan hw->switch_info->recp_list = recps; 11480d144c9SAnirudh Venkataramanan 11580d144c9SAnirudh Venkataramanan return 0; 11680d144c9SAnirudh Venkataramanan } 11780d144c9SAnirudh Venkataramanan 11880d144c9SAnirudh Venkataramanan /** 1199c20346bSAnirudh Venkataramanan * ice_aq_get_sw_cfg - get switch configuration 1209c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 1219c20346bSAnirudh Venkataramanan * @buf: pointer to the result buffer 1229c20346bSAnirudh Venkataramanan * @buf_size: length of the buffer available for response 1239c20346bSAnirudh Venkataramanan * @req_desc: pointer to requested descriptor 1249c20346bSAnirudh Venkataramanan * @num_elems: pointer to number of elements 1259c20346bSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 1269c20346bSAnirudh Venkataramanan * 1279c20346bSAnirudh Venkataramanan * Get switch configuration (0x0200) to be placed in 'buff'. 1289c20346bSAnirudh Venkataramanan * This admin command returns information such as initial VSI/port number 1299c20346bSAnirudh Venkataramanan * and switch ID it belongs to. 1309c20346bSAnirudh Venkataramanan * 1319c20346bSAnirudh Venkataramanan * NOTE: *req_desc is both an input/output parameter. 1329c20346bSAnirudh Venkataramanan * The caller of this function first calls this function with *request_desc set 1339c20346bSAnirudh Venkataramanan * to 0. If the response from f/w has *req_desc set to 0, all the switch 1349c20346bSAnirudh Venkataramanan * configuration information has been returned; if non-zero (meaning not all 1359c20346bSAnirudh Venkataramanan * the information was returned), the caller should call this function again 1369c20346bSAnirudh Venkataramanan * with *req_desc set to the previous value returned by f/w to get the 1379c20346bSAnirudh Venkataramanan * next block of switch configuration information. 1389c20346bSAnirudh Venkataramanan * 1399c20346bSAnirudh Venkataramanan * *num_elems is output only parameter. This reflects the number of elements 1409c20346bSAnirudh Venkataramanan * in response buffer. The caller of this function to use *num_elems while 1419c20346bSAnirudh Venkataramanan * parsing the response buffer. 1429c20346bSAnirudh Venkataramanan */ 1439c20346bSAnirudh Venkataramanan static enum ice_status 1449c20346bSAnirudh Venkataramanan ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf, 1459c20346bSAnirudh Venkataramanan u16 buf_size, u16 *req_desc, u16 *num_elems, 1469c20346bSAnirudh Venkataramanan struct ice_sq_cd *cd) 1479c20346bSAnirudh Venkataramanan { 1489c20346bSAnirudh Venkataramanan struct ice_aqc_get_sw_cfg *cmd; 1499c20346bSAnirudh Venkataramanan enum ice_status status; 1509c20346bSAnirudh Venkataramanan struct ice_aq_desc desc; 1519c20346bSAnirudh Venkataramanan 1529c20346bSAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 1539c20346bSAnirudh Venkataramanan cmd = &desc.params.get_sw_conf; 1549c20346bSAnirudh Venkataramanan cmd->element = cpu_to_le16(*req_desc); 1559c20346bSAnirudh Venkataramanan 1569c20346bSAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 1579c20346bSAnirudh Venkataramanan if (!status) { 1589c20346bSAnirudh Venkataramanan *req_desc = le16_to_cpu(cmd->element); 1599c20346bSAnirudh Venkataramanan *num_elems = le16_to_cpu(cmd->num_elems); 1609c20346bSAnirudh Venkataramanan } 1619c20346bSAnirudh Venkataramanan 1629c20346bSAnirudh Venkataramanan return status; 1639c20346bSAnirudh Venkataramanan } 1649c20346bSAnirudh Venkataramanan 1653a858ba3SAnirudh Venkataramanan /** 1663a858ba3SAnirudh Venkataramanan * ice_aq_add_vsi 1673a858ba3SAnirudh Venkataramanan * @hw: pointer to the hw struct 1683a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 1693a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 1703a858ba3SAnirudh Venkataramanan * 1713a858ba3SAnirudh Venkataramanan * Add a VSI context to the hardware (0x0210) 1723a858ba3SAnirudh Venkataramanan */ 1730f9d5027SAnirudh Venkataramanan static enum ice_status 1743a858ba3SAnirudh Venkataramanan ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1753a858ba3SAnirudh Venkataramanan struct ice_sq_cd *cd) 1763a858ba3SAnirudh Venkataramanan { 1773a858ba3SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *res; 1783a858ba3SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 1793a858ba3SAnirudh Venkataramanan struct ice_aq_desc desc; 1800f9d5027SAnirudh Venkataramanan enum ice_status status; 1813a858ba3SAnirudh Venkataramanan 1823a858ba3SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 1830f9d5027SAnirudh Venkataramanan res = &desc.params.add_update_free_vsi_res; 1843a858ba3SAnirudh Venkataramanan 1853a858ba3SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 1863a858ba3SAnirudh Venkataramanan 1873a858ba3SAnirudh Venkataramanan if (!vsi_ctx->alloc_from_pool) 1883a858ba3SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | 1893a858ba3SAnirudh Venkataramanan ICE_AQ_VSI_IS_VALID); 1903a858ba3SAnirudh Venkataramanan 1913a858ba3SAnirudh Venkataramanan cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags); 1923a858ba3SAnirudh Venkataramanan 1933a858ba3SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 1943a858ba3SAnirudh Venkataramanan 1953a858ba3SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1963a858ba3SAnirudh Venkataramanan sizeof(vsi_ctx->info), cd); 1973a858ba3SAnirudh Venkataramanan 1983a858ba3SAnirudh Venkataramanan if (!status) { 1993a858ba3SAnirudh Venkataramanan vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M; 2003a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used); 2013a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free); 2023a858ba3SAnirudh Venkataramanan } 2033a858ba3SAnirudh Venkataramanan 2043a858ba3SAnirudh Venkataramanan return status; 2053a858ba3SAnirudh Venkataramanan } 2063a858ba3SAnirudh Venkataramanan 2073a858ba3SAnirudh Venkataramanan /** 2080f9d5027SAnirudh Venkataramanan * ice_aq_free_vsi 2090f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 2100f9d5027SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 2110f9d5027SAnirudh Venkataramanan * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 2120f9d5027SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 2130f9d5027SAnirudh Venkataramanan * 2140f9d5027SAnirudh Venkataramanan * Free VSI context info from hardware (0x0213) 2150f9d5027SAnirudh Venkataramanan */ 2160f9d5027SAnirudh Venkataramanan static enum ice_status 2170f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 2180f9d5027SAnirudh Venkataramanan bool keep_vsi_alloc, struct ice_sq_cd *cd) 2190f9d5027SAnirudh Venkataramanan { 2200f9d5027SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *resp; 2210f9d5027SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 2220f9d5027SAnirudh Venkataramanan struct ice_aq_desc desc; 2230f9d5027SAnirudh Venkataramanan enum ice_status status; 2240f9d5027SAnirudh Venkataramanan 2250f9d5027SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 2260f9d5027SAnirudh Venkataramanan resp = &desc.params.add_update_free_vsi_res; 2270f9d5027SAnirudh Venkataramanan 2280f9d5027SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 2290f9d5027SAnirudh Venkataramanan 2300f9d5027SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 2310f9d5027SAnirudh Venkataramanan if (keep_vsi_alloc) 2320f9d5027SAnirudh Venkataramanan cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC); 2330f9d5027SAnirudh Venkataramanan 2340f9d5027SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 2350f9d5027SAnirudh Venkataramanan if (!status) { 2360f9d5027SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 2370f9d5027SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 2380f9d5027SAnirudh Venkataramanan } 2390f9d5027SAnirudh Venkataramanan 2400f9d5027SAnirudh Venkataramanan return status; 2410f9d5027SAnirudh Venkataramanan } 2420f9d5027SAnirudh Venkataramanan 2430f9d5027SAnirudh Venkataramanan /** 2443a858ba3SAnirudh Venkataramanan * ice_aq_update_vsi 2453a858ba3SAnirudh Venkataramanan * @hw: pointer to the hw struct 2463a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 2473a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 2483a858ba3SAnirudh Venkataramanan * 2493a858ba3SAnirudh Venkataramanan * Update VSI context in the hardware (0x0211) 2503a858ba3SAnirudh Venkataramanan */ 2515726ca0eSAnirudh Venkataramanan static enum ice_status 2523a858ba3SAnirudh Venkataramanan ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 2533a858ba3SAnirudh Venkataramanan struct ice_sq_cd *cd) 2543a858ba3SAnirudh Venkataramanan { 2553a858ba3SAnirudh Venkataramanan struct ice_aqc_add_update_free_vsi_resp *resp; 2563a858ba3SAnirudh Venkataramanan struct ice_aqc_add_get_update_free_vsi *cmd; 2573a858ba3SAnirudh Venkataramanan struct ice_aq_desc desc; 2583a858ba3SAnirudh Venkataramanan enum ice_status status; 2593a858ba3SAnirudh Venkataramanan 2603a858ba3SAnirudh Venkataramanan cmd = &desc.params.vsi_cmd; 2610f9d5027SAnirudh Venkataramanan resp = &desc.params.add_update_free_vsi_res; 2623a858ba3SAnirudh Venkataramanan 2633a858ba3SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 2643a858ba3SAnirudh Venkataramanan 2653a858ba3SAnirudh Venkataramanan cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 2663a858ba3SAnirudh Venkataramanan 2673a858ba3SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 2683a858ba3SAnirudh Venkataramanan 2693a858ba3SAnirudh Venkataramanan status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 2703a858ba3SAnirudh Venkataramanan sizeof(vsi_ctx->info), cd); 2713a858ba3SAnirudh Venkataramanan 2723a858ba3SAnirudh Venkataramanan if (!status) { 2733a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 2743a858ba3SAnirudh Venkataramanan vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 2753a858ba3SAnirudh Venkataramanan } 2763a858ba3SAnirudh Venkataramanan 2773a858ba3SAnirudh Venkataramanan return status; 2783a858ba3SAnirudh Venkataramanan } 2793a858ba3SAnirudh Venkataramanan 2803a858ba3SAnirudh Venkataramanan /** 2810f9d5027SAnirudh Venkataramanan * ice_is_vsi_valid - check whether the VSI is valid or not 2823a858ba3SAnirudh Venkataramanan * @hw: pointer to the hw struct 2830f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2840f9d5027SAnirudh Venkataramanan * 2850f9d5027SAnirudh Venkataramanan * check whether the VSI is valid or not 2860f9d5027SAnirudh Venkataramanan */ 2874fb33f31SAnirudh Venkataramanan bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 2880f9d5027SAnirudh Venkataramanan { 2890f9d5027SAnirudh Venkataramanan return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 2900f9d5027SAnirudh Venkataramanan } 2910f9d5027SAnirudh Venkataramanan 2920f9d5027SAnirudh Venkataramanan /** 2930f9d5027SAnirudh Venkataramanan * ice_get_hw_vsi_num - return the hw VSI number 2940f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 2950f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 2960f9d5027SAnirudh Venkataramanan * 2970f9d5027SAnirudh Venkataramanan * return the hw VSI number 2980f9d5027SAnirudh Venkataramanan * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 2990f9d5027SAnirudh Venkataramanan */ 3004fb33f31SAnirudh Venkataramanan u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 3010f9d5027SAnirudh Venkataramanan { 3020f9d5027SAnirudh Venkataramanan return hw->vsi_ctx[vsi_handle]->vsi_num; 3030f9d5027SAnirudh Venkataramanan } 3040f9d5027SAnirudh Venkataramanan 3050f9d5027SAnirudh Venkataramanan /** 3060f9d5027SAnirudh Venkataramanan * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 3070f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 3080f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 3090f9d5027SAnirudh Venkataramanan * 3100f9d5027SAnirudh Venkataramanan * return the VSI context entry for a given VSI handle 3110f9d5027SAnirudh Venkataramanan */ 3124fb33f31SAnirudh Venkataramanan struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 3130f9d5027SAnirudh Venkataramanan { 3140f9d5027SAnirudh Venkataramanan return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 3150f9d5027SAnirudh Venkataramanan } 3160f9d5027SAnirudh Venkataramanan 3170f9d5027SAnirudh Venkataramanan /** 3180f9d5027SAnirudh Venkataramanan * ice_save_vsi_ctx - save the VSI context for a given VSI handle 3190f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 3200f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 3210f9d5027SAnirudh Venkataramanan * @vsi: VSI context pointer 3220f9d5027SAnirudh Venkataramanan * 3230f9d5027SAnirudh Venkataramanan * save the VSI context entry for a given VSI handle 3240f9d5027SAnirudh Venkataramanan */ 3250f9d5027SAnirudh Venkataramanan static void ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, 3260f9d5027SAnirudh Venkataramanan struct ice_vsi_ctx *vsi) 3270f9d5027SAnirudh Venkataramanan { 3280f9d5027SAnirudh Venkataramanan hw->vsi_ctx[vsi_handle] = vsi; 3290f9d5027SAnirudh Venkataramanan } 3300f9d5027SAnirudh Venkataramanan 3310f9d5027SAnirudh Venkataramanan /** 3320f9d5027SAnirudh Venkataramanan * ice_clear_vsi_ctx - clear the VSI context entry 3330f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 3340f9d5027SAnirudh Venkataramanan * @vsi_handle: VSI handle 3350f9d5027SAnirudh Venkataramanan * 3360f9d5027SAnirudh Venkataramanan * clear the VSI context entry 3370f9d5027SAnirudh Venkataramanan */ 3380f9d5027SAnirudh Venkataramanan static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 3390f9d5027SAnirudh Venkataramanan { 3400f9d5027SAnirudh Venkataramanan struct ice_vsi_ctx *vsi; 3410f9d5027SAnirudh Venkataramanan 3420f9d5027SAnirudh Venkataramanan vsi = ice_get_vsi_ctx(hw, vsi_handle); 3430f9d5027SAnirudh Venkataramanan if (vsi) { 3440f9d5027SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), vsi); 3450f9d5027SAnirudh Venkataramanan hw->vsi_ctx[vsi_handle] = NULL; 3460f9d5027SAnirudh Venkataramanan } 3470f9d5027SAnirudh Venkataramanan } 3480f9d5027SAnirudh Venkataramanan 3490f9d5027SAnirudh Venkataramanan /** 3500f9d5027SAnirudh Venkataramanan * ice_add_vsi - add VSI context to the hardware and VSI handle list 3510f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 3520f9d5027SAnirudh Venkataramanan * @vsi_handle: unique VSI handle provided by drivers 3530f9d5027SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 3540f9d5027SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 3550f9d5027SAnirudh Venkataramanan * 3560f9d5027SAnirudh Venkataramanan * Add a VSI context to the hardware also add it into the VSI handle list. 3570f9d5027SAnirudh Venkataramanan * If this function gets called after reset for existing VSIs then update 3580f9d5027SAnirudh Venkataramanan * with the new HW VSI number in the corresponding VSI handle list entry. 3590f9d5027SAnirudh Venkataramanan */ 3600f9d5027SAnirudh Venkataramanan enum ice_status 3610f9d5027SAnirudh Venkataramanan ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 3620f9d5027SAnirudh Venkataramanan struct ice_sq_cd *cd) 3630f9d5027SAnirudh Venkataramanan { 3640f9d5027SAnirudh Venkataramanan struct ice_vsi_ctx *tmp_vsi_ctx; 3650f9d5027SAnirudh Venkataramanan enum ice_status status; 3660f9d5027SAnirudh Venkataramanan 3670f9d5027SAnirudh Venkataramanan if (vsi_handle >= ICE_MAX_VSI) 3680f9d5027SAnirudh Venkataramanan return ICE_ERR_PARAM; 3690f9d5027SAnirudh Venkataramanan status = ice_aq_add_vsi(hw, vsi_ctx, cd); 3700f9d5027SAnirudh Venkataramanan if (status) 3710f9d5027SAnirudh Venkataramanan return status; 3720f9d5027SAnirudh Venkataramanan tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 3730f9d5027SAnirudh Venkataramanan if (!tmp_vsi_ctx) { 3740f9d5027SAnirudh Venkataramanan /* Create a new vsi context */ 3750f9d5027SAnirudh Venkataramanan tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw), 3760f9d5027SAnirudh Venkataramanan sizeof(*tmp_vsi_ctx), GFP_KERNEL); 3770f9d5027SAnirudh Venkataramanan if (!tmp_vsi_ctx) { 3780f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(hw, vsi_ctx, false, cd); 3790f9d5027SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 3800f9d5027SAnirudh Venkataramanan } 3810f9d5027SAnirudh Venkataramanan *tmp_vsi_ctx = *vsi_ctx; 3820f9d5027SAnirudh Venkataramanan ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 3830f9d5027SAnirudh Venkataramanan } else { 3840f9d5027SAnirudh Venkataramanan /* update with new HW VSI num */ 3855726ca0eSAnirudh Venkataramanan if (tmp_vsi_ctx->vsi_num != vsi_ctx->vsi_num) 3860f9d5027SAnirudh Venkataramanan tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 3870f9d5027SAnirudh Venkataramanan } 3880f9d5027SAnirudh Venkataramanan 3890f9d5027SAnirudh Venkataramanan return status; 3900f9d5027SAnirudh Venkataramanan } 3910f9d5027SAnirudh Venkataramanan 3920f9d5027SAnirudh Venkataramanan /** 3930f9d5027SAnirudh Venkataramanan * ice_free_vsi- free VSI context from hardware and VSI handle list 3940f9d5027SAnirudh Venkataramanan * @hw: pointer to the hw struct 3950f9d5027SAnirudh Venkataramanan * @vsi_handle: unique VSI handle 3963a858ba3SAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 3973a858ba3SAnirudh Venkataramanan * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 3983a858ba3SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 3993a858ba3SAnirudh Venkataramanan * 4000f9d5027SAnirudh Venkataramanan * Free VSI context info from hardware as well as from VSI handle list 4013a858ba3SAnirudh Venkataramanan */ 4023a858ba3SAnirudh Venkataramanan enum ice_status 4030f9d5027SAnirudh Venkataramanan ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 4043a858ba3SAnirudh Venkataramanan bool keep_vsi_alloc, struct ice_sq_cd *cd) 4053a858ba3SAnirudh Venkataramanan { 4063a858ba3SAnirudh Venkataramanan enum ice_status status; 4073a858ba3SAnirudh Venkataramanan 4080f9d5027SAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 4090f9d5027SAnirudh Venkataramanan return ICE_ERR_PARAM; 4100f9d5027SAnirudh Venkataramanan vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 4110f9d5027SAnirudh Venkataramanan status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 4120f9d5027SAnirudh Venkataramanan if (!status) 4130f9d5027SAnirudh Venkataramanan ice_clear_vsi_ctx(hw, vsi_handle); 4143a858ba3SAnirudh Venkataramanan return status; 4153a858ba3SAnirudh Venkataramanan } 4163a858ba3SAnirudh Venkataramanan 4179daf8208SAnirudh Venkataramanan /** 4185726ca0eSAnirudh Venkataramanan * ice_update_vsi 4195726ca0eSAnirudh Venkataramanan * @hw: pointer to the hw struct 4205726ca0eSAnirudh Venkataramanan * @vsi_handle: unique VSI handle 4215726ca0eSAnirudh Venkataramanan * @vsi_ctx: pointer to a VSI context struct 4225726ca0eSAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 4235726ca0eSAnirudh Venkataramanan * 4245726ca0eSAnirudh Venkataramanan * Update VSI context in the hardware 4255726ca0eSAnirudh Venkataramanan */ 4265726ca0eSAnirudh Venkataramanan enum ice_status 4275726ca0eSAnirudh Venkataramanan ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 4285726ca0eSAnirudh Venkataramanan struct ice_sq_cd *cd) 4295726ca0eSAnirudh Venkataramanan { 4305726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 4315726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 4325726ca0eSAnirudh Venkataramanan vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 4335726ca0eSAnirudh Venkataramanan return ice_aq_update_vsi(hw, vsi_ctx, cd); 4345726ca0eSAnirudh Venkataramanan } 4355726ca0eSAnirudh Venkataramanan 4365726ca0eSAnirudh Venkataramanan /** 4379daf8208SAnirudh Venkataramanan * ice_aq_alloc_free_vsi_list 4389daf8208SAnirudh Venkataramanan * @hw: pointer to the hw struct 4399daf8208SAnirudh Venkataramanan * @vsi_list_id: VSI list id returned or used for lookup 4409daf8208SAnirudh Venkataramanan * @lkup_type: switch rule filter lookup type 4419daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 4429daf8208SAnirudh Venkataramanan * 4439daf8208SAnirudh Venkataramanan * allocates or free a VSI list resource 4449daf8208SAnirudh Venkataramanan */ 4459daf8208SAnirudh Venkataramanan static enum ice_status 4469daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 4479daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type, 4489daf8208SAnirudh Venkataramanan enum ice_adminq_opc opc) 4499daf8208SAnirudh Venkataramanan { 4509daf8208SAnirudh Venkataramanan struct ice_aqc_alloc_free_res_elem *sw_buf; 4519daf8208SAnirudh Venkataramanan struct ice_aqc_res_elem *vsi_ele; 4529daf8208SAnirudh Venkataramanan enum ice_status status; 4539daf8208SAnirudh Venkataramanan u16 buf_len; 4549daf8208SAnirudh Venkataramanan 4559daf8208SAnirudh Venkataramanan buf_len = sizeof(*sw_buf); 4569daf8208SAnirudh Venkataramanan sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL); 4579daf8208SAnirudh Venkataramanan if (!sw_buf) 4589daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 4599daf8208SAnirudh Venkataramanan sw_buf->num_elems = cpu_to_le16(1); 4609daf8208SAnirudh Venkataramanan 4619daf8208SAnirudh Venkataramanan if (lkup_type == ICE_SW_LKUP_MAC || 4629daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_MAC_VLAN || 4639daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE || 4649daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 4659daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC || 4669daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC_VLAN) { 4679daf8208SAnirudh Venkataramanan sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 4689daf8208SAnirudh Venkataramanan } else if (lkup_type == ICE_SW_LKUP_VLAN) { 4699daf8208SAnirudh Venkataramanan sw_buf->res_type = 4709daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 4719daf8208SAnirudh Venkataramanan } else { 4729daf8208SAnirudh Venkataramanan status = ICE_ERR_PARAM; 4739daf8208SAnirudh Venkataramanan goto ice_aq_alloc_free_vsi_list_exit; 4749daf8208SAnirudh Venkataramanan } 4759daf8208SAnirudh Venkataramanan 4769daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_free_res) 4779daf8208SAnirudh Venkataramanan sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id); 4789daf8208SAnirudh Venkataramanan 4799daf8208SAnirudh Venkataramanan status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); 4809daf8208SAnirudh Venkataramanan if (status) 4819daf8208SAnirudh Venkataramanan goto ice_aq_alloc_free_vsi_list_exit; 4829daf8208SAnirudh Venkataramanan 4839daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_alloc_res) { 4849daf8208SAnirudh Venkataramanan vsi_ele = &sw_buf->elem[0]; 4859daf8208SAnirudh Venkataramanan *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp); 4869daf8208SAnirudh Venkataramanan } 4879daf8208SAnirudh Venkataramanan 4889daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list_exit: 4899daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), sw_buf); 4909daf8208SAnirudh Venkataramanan return status; 4919daf8208SAnirudh Venkataramanan } 4929daf8208SAnirudh Venkataramanan 4939daf8208SAnirudh Venkataramanan /** 4949daf8208SAnirudh Venkataramanan * ice_aq_sw_rules - add/update/remove switch rules 4959daf8208SAnirudh Venkataramanan * @hw: pointer to the hw struct 4969daf8208SAnirudh Venkataramanan * @rule_list: pointer to switch rule population list 4979daf8208SAnirudh Venkataramanan * @rule_list_sz: total size of the rule list in bytes 4989daf8208SAnirudh Venkataramanan * @num_rules: number of switch rules in the rule_list 4999daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 5009daf8208SAnirudh Venkataramanan * @cd: pointer to command details structure or NULL 5019daf8208SAnirudh Venkataramanan * 5029daf8208SAnirudh Venkataramanan * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 5039daf8208SAnirudh Venkataramanan */ 5049daf8208SAnirudh Venkataramanan static enum ice_status 5059daf8208SAnirudh Venkataramanan ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 5069daf8208SAnirudh Venkataramanan u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 5079daf8208SAnirudh Venkataramanan { 5089daf8208SAnirudh Venkataramanan struct ice_aq_desc desc; 5099daf8208SAnirudh Venkataramanan 5109daf8208SAnirudh Venkataramanan if (opc != ice_aqc_opc_add_sw_rules && 5119daf8208SAnirudh Venkataramanan opc != ice_aqc_opc_update_sw_rules && 5129daf8208SAnirudh Venkataramanan opc != ice_aqc_opc_remove_sw_rules) 5139daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 5149daf8208SAnirudh Venkataramanan 5159daf8208SAnirudh Venkataramanan ice_fill_dflt_direct_cmd_desc(&desc, opc); 5169daf8208SAnirudh Venkataramanan 5179daf8208SAnirudh Venkataramanan desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 5189daf8208SAnirudh Venkataramanan desc.params.sw_rules.num_rules_fltr_entry_index = 5199daf8208SAnirudh Venkataramanan cpu_to_le16(num_rules); 5209daf8208SAnirudh Venkataramanan return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 5219daf8208SAnirudh Venkataramanan } 5229daf8208SAnirudh Venkataramanan 5239c20346bSAnirudh Venkataramanan /* ice_init_port_info - Initialize port_info with switch configuration data 5249c20346bSAnirudh Venkataramanan * @pi: pointer to port_info 5259c20346bSAnirudh Venkataramanan * @vsi_port_num: VSI number or port number 5269c20346bSAnirudh Venkataramanan * @type: Type of switch element (port or VSI) 5279c20346bSAnirudh Venkataramanan * @swid: switch ID of the switch the element is attached to 5289c20346bSAnirudh Venkataramanan * @pf_vf_num: PF or VF number 5299c20346bSAnirudh Venkataramanan * @is_vf: true if the element is a VF, false otherwise 5309c20346bSAnirudh Venkataramanan */ 5319c20346bSAnirudh Venkataramanan static void 5329c20346bSAnirudh Venkataramanan ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 5339c20346bSAnirudh Venkataramanan u16 swid, u16 pf_vf_num, bool is_vf) 5349c20346bSAnirudh Venkataramanan { 5359c20346bSAnirudh Venkataramanan switch (type) { 5369c20346bSAnirudh Venkataramanan case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 5379c20346bSAnirudh Venkataramanan pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 5389c20346bSAnirudh Venkataramanan pi->sw_id = swid; 5399c20346bSAnirudh Venkataramanan pi->pf_vf_num = pf_vf_num; 5409c20346bSAnirudh Venkataramanan pi->is_vf = is_vf; 5419c20346bSAnirudh Venkataramanan pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 5429c20346bSAnirudh Venkataramanan pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 5439c20346bSAnirudh Venkataramanan break; 5449c20346bSAnirudh Venkataramanan default: 5459c20346bSAnirudh Venkataramanan ice_debug(pi->hw, ICE_DBG_SW, 5469c20346bSAnirudh Venkataramanan "incorrect VSI/port type received\n"); 5479c20346bSAnirudh Venkataramanan break; 5489c20346bSAnirudh Venkataramanan } 5499c20346bSAnirudh Venkataramanan } 5509c20346bSAnirudh Venkataramanan 5519c20346bSAnirudh Venkataramanan /* ice_get_initial_sw_cfg - Get initial port and default VSI data 5529c20346bSAnirudh Venkataramanan * @hw: pointer to the hardware structure 5539c20346bSAnirudh Venkataramanan */ 5549c20346bSAnirudh Venkataramanan enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) 5559c20346bSAnirudh Venkataramanan { 5569c20346bSAnirudh Venkataramanan struct ice_aqc_get_sw_cfg_resp *rbuf; 5579c20346bSAnirudh Venkataramanan enum ice_status status; 5589c20346bSAnirudh Venkataramanan u16 req_desc = 0; 5599c20346bSAnirudh Venkataramanan u16 num_elems; 5609c20346bSAnirudh Venkataramanan u16 i; 5619c20346bSAnirudh Venkataramanan 5629c20346bSAnirudh Venkataramanan rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN, 5639c20346bSAnirudh Venkataramanan GFP_KERNEL); 5649c20346bSAnirudh Venkataramanan 5659c20346bSAnirudh Venkataramanan if (!rbuf) 5669c20346bSAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 5679c20346bSAnirudh Venkataramanan 5689c20346bSAnirudh Venkataramanan /* Multiple calls to ice_aq_get_sw_cfg may be required 5699c20346bSAnirudh Venkataramanan * to get all the switch configuration information. The need 5709c20346bSAnirudh Venkataramanan * for additional calls is indicated by ice_aq_get_sw_cfg 5719c20346bSAnirudh Venkataramanan * writing a non-zero value in req_desc 5729c20346bSAnirudh Venkataramanan */ 5739c20346bSAnirudh Venkataramanan do { 5749c20346bSAnirudh Venkataramanan status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 5759c20346bSAnirudh Venkataramanan &req_desc, &num_elems, NULL); 5769c20346bSAnirudh Venkataramanan 5779c20346bSAnirudh Venkataramanan if (status) 5789c20346bSAnirudh Venkataramanan break; 5799c20346bSAnirudh Venkataramanan 5809c20346bSAnirudh Venkataramanan for (i = 0; i < num_elems; i++) { 5819c20346bSAnirudh Venkataramanan struct ice_aqc_get_sw_cfg_resp_elem *ele; 5829c20346bSAnirudh Venkataramanan u16 pf_vf_num, swid, vsi_port_num; 5839c20346bSAnirudh Venkataramanan bool is_vf = false; 5849c20346bSAnirudh Venkataramanan u8 type; 5859c20346bSAnirudh Venkataramanan 5869c20346bSAnirudh Venkataramanan ele = rbuf[i].elements; 5879c20346bSAnirudh Venkataramanan vsi_port_num = le16_to_cpu(ele->vsi_port_num) & 5889c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 5899c20346bSAnirudh Venkataramanan 5909c20346bSAnirudh Venkataramanan pf_vf_num = le16_to_cpu(ele->pf_vf_num) & 5919c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 5929c20346bSAnirudh Venkataramanan 5939c20346bSAnirudh Venkataramanan swid = le16_to_cpu(ele->swid); 5949c20346bSAnirudh Venkataramanan 5959c20346bSAnirudh Venkataramanan if (le16_to_cpu(ele->pf_vf_num) & 5969c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_IS_VF) 5979c20346bSAnirudh Venkataramanan is_vf = true; 5989c20346bSAnirudh Venkataramanan 5999c20346bSAnirudh Venkataramanan type = le16_to_cpu(ele->vsi_port_num) >> 6009c20346bSAnirudh Venkataramanan ICE_AQC_GET_SW_CONF_RESP_TYPE_S; 6019c20346bSAnirudh Venkataramanan 6029c20346bSAnirudh Venkataramanan if (type == ICE_AQC_GET_SW_CONF_RESP_VSI) { 6039c20346bSAnirudh Venkataramanan /* FW VSI is not needed. Just continue. */ 6049c20346bSAnirudh Venkataramanan continue; 6059c20346bSAnirudh Venkataramanan } 6069c20346bSAnirudh Venkataramanan 6079c20346bSAnirudh Venkataramanan ice_init_port_info(hw->port_info, vsi_port_num, 6089c20346bSAnirudh Venkataramanan type, swid, pf_vf_num, is_vf); 6099c20346bSAnirudh Venkataramanan } 6109c20346bSAnirudh Venkataramanan } while (req_desc && !status); 6119c20346bSAnirudh Venkataramanan 6129c20346bSAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), (void *)rbuf); 6139c20346bSAnirudh Venkataramanan return status; 6149c20346bSAnirudh Venkataramanan } 6159daf8208SAnirudh Venkataramanan 6169daf8208SAnirudh Venkataramanan /** 6179daf8208SAnirudh Venkataramanan * ice_fill_sw_info - Helper function to populate lb_en and lan_en 6189daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 6199daf8208SAnirudh Venkataramanan * @f_info: filter info structure to fill/update 6209daf8208SAnirudh Venkataramanan * 6219daf8208SAnirudh Venkataramanan * This helper function populates the lb_en and lan_en elements of the provided 6229daf8208SAnirudh Venkataramanan * ice_fltr_info struct using the switch's type and characteristics of the 6239daf8208SAnirudh Venkataramanan * switch rule being configured. 6249daf8208SAnirudh Venkataramanan */ 6259daf8208SAnirudh Venkataramanan static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *f_info) 6269daf8208SAnirudh Venkataramanan { 6279daf8208SAnirudh Venkataramanan f_info->lb_en = false; 6289daf8208SAnirudh Venkataramanan f_info->lan_en = false; 6299daf8208SAnirudh Venkataramanan if ((f_info->flag & ICE_FLTR_TX) && 6309daf8208SAnirudh Venkataramanan (f_info->fltr_act == ICE_FWD_TO_VSI || 6319daf8208SAnirudh Venkataramanan f_info->fltr_act == ICE_FWD_TO_VSI_LIST || 6329daf8208SAnirudh Venkataramanan f_info->fltr_act == ICE_FWD_TO_Q || 6339daf8208SAnirudh Venkataramanan f_info->fltr_act == ICE_FWD_TO_QGRP)) { 6349daf8208SAnirudh Venkataramanan f_info->lb_en = true; 6359daf8208SAnirudh Venkataramanan if (!(hw->evb_veb && f_info->lkup_type == ICE_SW_LKUP_MAC && 6369daf8208SAnirudh Venkataramanan is_unicast_ether_addr(f_info->l_data.mac.mac_addr))) 6379daf8208SAnirudh Venkataramanan f_info->lan_en = true; 6389daf8208SAnirudh Venkataramanan } 6399daf8208SAnirudh Venkataramanan } 6409daf8208SAnirudh Venkataramanan 6419daf8208SAnirudh Venkataramanan /** 6429daf8208SAnirudh Venkataramanan * ice_fill_sw_rule - Helper function to fill switch rule structure 6439daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 6449daf8208SAnirudh Venkataramanan * @f_info: entry containing packet forwarding information 6459daf8208SAnirudh Venkataramanan * @s_rule: switch rule structure to be filled in based on mac_entry 6469daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 6479daf8208SAnirudh Venkataramanan */ 6489daf8208SAnirudh Venkataramanan static void 6499daf8208SAnirudh Venkataramanan ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 6509daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc) 6519daf8208SAnirudh Venkataramanan { 6529daf8208SAnirudh Venkataramanan u16 vlan_id = ICE_MAX_VLAN_ID + 1; 6539daf8208SAnirudh Venkataramanan void *daddr = NULL; 65474118f7aSZhenning Xiao u16 eth_hdr_sz; 65574118f7aSZhenning Xiao u8 *eth_hdr; 6569daf8208SAnirudh Venkataramanan u32 act = 0; 6579daf8208SAnirudh Venkataramanan __be16 *off; 6589daf8208SAnirudh Venkataramanan 6599daf8208SAnirudh Venkataramanan if (opc == ice_aqc_opc_remove_sw_rules) { 6609daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.act = 0; 6619daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.index = 6629daf8208SAnirudh Venkataramanan cpu_to_le16(f_info->fltr_rule_id); 6639daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.hdr_len = 0; 6649daf8208SAnirudh Venkataramanan return; 6659daf8208SAnirudh Venkataramanan } 6669daf8208SAnirudh Venkataramanan 66774118f7aSZhenning Xiao eth_hdr_sz = sizeof(dummy_eth_header); 66874118f7aSZhenning Xiao eth_hdr = s_rule->pdata.lkup_tx_rx.hdr; 66974118f7aSZhenning Xiao 6709daf8208SAnirudh Venkataramanan /* initialize the ether header with a dummy header */ 67174118f7aSZhenning Xiao memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz); 6729daf8208SAnirudh Venkataramanan ice_fill_sw_info(hw, f_info); 6739daf8208SAnirudh Venkataramanan 6749daf8208SAnirudh Venkataramanan switch (f_info->fltr_act) { 6759daf8208SAnirudh Venkataramanan case ICE_FWD_TO_VSI: 6765726ca0eSAnirudh Venkataramanan act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 6779daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_ID_M; 6789daf8208SAnirudh Venkataramanan if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 6799daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | 6809daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VALID_BIT; 6819daf8208SAnirudh Venkataramanan break; 6829daf8208SAnirudh Venkataramanan case ICE_FWD_TO_VSI_LIST: 6839daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_LIST; 6849daf8208SAnirudh Venkataramanan act |= (f_info->fwd_id.vsi_list_id << 6859daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_LIST_ID_S) & 6869daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VSI_LIST_ID_M; 6879daf8208SAnirudh Venkataramanan if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 6889daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | 6899daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_VALID_BIT; 6909daf8208SAnirudh Venkataramanan break; 6919daf8208SAnirudh Venkataramanan case ICE_FWD_TO_Q: 6929daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_TO_Q; 6939daf8208SAnirudh Venkataramanan act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 6949daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_Q_INDEX_M; 6959daf8208SAnirudh Venkataramanan break; 6969daf8208SAnirudh Venkataramanan case ICE_FWD_TO_QGRP: 6979daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_TO_Q; 6989daf8208SAnirudh Venkataramanan act |= (f_info->qgrp_size << ICE_SINGLE_ACT_Q_REGION_S) & 6999daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_Q_REGION_M; 7009daf8208SAnirudh Venkataramanan break; 7019daf8208SAnirudh Venkataramanan case ICE_DROP_PACKET: 7029daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP; 7039daf8208SAnirudh Venkataramanan break; 7049daf8208SAnirudh Venkataramanan default: 7059daf8208SAnirudh Venkataramanan return; 7069daf8208SAnirudh Venkataramanan } 7079daf8208SAnirudh Venkataramanan 7089daf8208SAnirudh Venkataramanan if (f_info->lb_en) 7099daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_LB_ENABLE; 7109daf8208SAnirudh Venkataramanan if (f_info->lan_en) 7119daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_LAN_ENABLE; 7129daf8208SAnirudh Venkataramanan 7139daf8208SAnirudh Venkataramanan switch (f_info->lkup_type) { 7149daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC: 7159daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac.mac_addr; 7169daf8208SAnirudh Venkataramanan break; 7179daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_VLAN: 7189daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.vlan.vlan_id; 7199daf8208SAnirudh Venkataramanan if (f_info->fltr_act == ICE_FWD_TO_VSI || 7209daf8208SAnirudh Venkataramanan f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 7219daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_PRUNE; 7229daf8208SAnirudh Venkataramanan act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 7239daf8208SAnirudh Venkataramanan } 7249daf8208SAnirudh Venkataramanan break; 7259daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE_MAC: 7269daf8208SAnirudh Venkataramanan daddr = f_info->l_data.ethertype_mac.mac_addr; 7279daf8208SAnirudh Venkataramanan /* fall-through */ 7289daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE: 72974118f7aSZhenning Xiao off = (__be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 7309daf8208SAnirudh Venkataramanan *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype); 7319daf8208SAnirudh Venkataramanan break; 7329daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC_VLAN: 7339daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac_vlan.mac_addr; 7349daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.mac_vlan.vlan_id; 7359daf8208SAnirudh Venkataramanan break; 7369daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC_VLAN: 7379daf8208SAnirudh Venkataramanan vlan_id = f_info->l_data.mac_vlan.vlan_id; 7389daf8208SAnirudh Venkataramanan /* fall-through */ 7399daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC: 7409daf8208SAnirudh Venkataramanan daddr = f_info->l_data.mac_vlan.mac_addr; 7419daf8208SAnirudh Venkataramanan break; 7429daf8208SAnirudh Venkataramanan default: 7439daf8208SAnirudh Venkataramanan break; 7449daf8208SAnirudh Venkataramanan } 7459daf8208SAnirudh Venkataramanan 7469daf8208SAnirudh Venkataramanan s_rule->type = (f_info->flag & ICE_FLTR_RX) ? 7479daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) : 7489daf8208SAnirudh Venkataramanan cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); 7499daf8208SAnirudh Venkataramanan 7509daf8208SAnirudh Venkataramanan /* Recipe set depending on lookup type */ 7519daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(f_info->lkup_type); 7529daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(f_info->src); 7539daf8208SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act); 7549daf8208SAnirudh Venkataramanan 7559daf8208SAnirudh Venkataramanan if (daddr) 75674118f7aSZhenning Xiao ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr); 7579daf8208SAnirudh Venkataramanan 7589daf8208SAnirudh Venkataramanan if (!(vlan_id > ICE_MAX_VLAN_ID)) { 75974118f7aSZhenning Xiao off = (__be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 7609daf8208SAnirudh Venkataramanan *off = cpu_to_be16(vlan_id); 7619daf8208SAnirudh Venkataramanan } 7629daf8208SAnirudh Venkataramanan 7639daf8208SAnirudh Venkataramanan /* Create the switch rule with the final dummy Ethernet header */ 7649daf8208SAnirudh Venkataramanan if (opc != ice_aqc_opc_update_sw_rules) 76574118f7aSZhenning Xiao s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(eth_hdr_sz); 7669daf8208SAnirudh Venkataramanan } 7679daf8208SAnirudh Venkataramanan 7689daf8208SAnirudh Venkataramanan /** 7699daf8208SAnirudh Venkataramanan * ice_add_marker_act 7709daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 7719daf8208SAnirudh Venkataramanan * @m_ent: the management entry for which sw marker needs to be added 7729daf8208SAnirudh Venkataramanan * @sw_marker: sw marker to tag the Rx descriptor with 7739daf8208SAnirudh Venkataramanan * @l_id: large action resource id 7749daf8208SAnirudh Venkataramanan * 7759daf8208SAnirudh Venkataramanan * Create a large action to hold software marker and update the switch rule 7769daf8208SAnirudh Venkataramanan * entry pointed by m_ent with newly created large action 7779daf8208SAnirudh Venkataramanan */ 7789daf8208SAnirudh Venkataramanan static enum ice_status 7799daf8208SAnirudh Venkataramanan ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 7809daf8208SAnirudh Venkataramanan u16 sw_marker, u16 l_id) 7819daf8208SAnirudh Venkataramanan { 7829daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *lg_act, *rx_tx; 7839daf8208SAnirudh Venkataramanan /* For software marker we need 3 large actions 7849daf8208SAnirudh Venkataramanan * 1. FWD action: FWD TO VSI or VSI LIST 7859daf8208SAnirudh Venkataramanan * 2. GENERIC VALUE action to hold the profile id 7869daf8208SAnirudh Venkataramanan * 3. GENERIC VALUE action to hold the software marker id 7879daf8208SAnirudh Venkataramanan */ 7889daf8208SAnirudh Venkataramanan const u16 num_lg_acts = 3; 7899daf8208SAnirudh Venkataramanan enum ice_status status; 7909daf8208SAnirudh Venkataramanan u16 lg_act_size; 7919daf8208SAnirudh Venkataramanan u16 rules_size; 7929daf8208SAnirudh Venkataramanan u32 act; 7935726ca0eSAnirudh Venkataramanan u16 id; 7949daf8208SAnirudh Venkataramanan 7959daf8208SAnirudh Venkataramanan if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 7969daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 7979daf8208SAnirudh Venkataramanan 7989daf8208SAnirudh Venkataramanan /* Create two back-to-back switch rules and submit them to the HW using 7999daf8208SAnirudh Venkataramanan * one memory buffer: 8009daf8208SAnirudh Venkataramanan * 1. Large Action 8019daf8208SAnirudh Venkataramanan * 2. Look up tx rx 8029daf8208SAnirudh Venkataramanan */ 8039daf8208SAnirudh Venkataramanan lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts); 8049daf8208SAnirudh Venkataramanan rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 8059daf8208SAnirudh Venkataramanan lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL); 8069daf8208SAnirudh Venkataramanan if (!lg_act) 8079daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 8089daf8208SAnirudh Venkataramanan 8099daf8208SAnirudh Venkataramanan rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size); 8109daf8208SAnirudh Venkataramanan 8119daf8208SAnirudh Venkataramanan /* Fill in the first switch rule i.e. large action */ 8129daf8208SAnirudh Venkataramanan lg_act->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT); 8139daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.index = cpu_to_le16(l_id); 8149daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.size = cpu_to_le16(num_lg_acts); 8159daf8208SAnirudh Venkataramanan 8169daf8208SAnirudh Venkataramanan /* First action VSI forwarding or VSI list forwarding depending on how 8179daf8208SAnirudh Venkataramanan * many VSIs 8189daf8208SAnirudh Venkataramanan */ 8195726ca0eSAnirudh Venkataramanan id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 8205726ca0eSAnirudh Venkataramanan m_ent->fltr_info.fwd_id.hw_vsi_id; 8219daf8208SAnirudh Venkataramanan 8229daf8208SAnirudh Venkataramanan act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 8235726ca0eSAnirudh Venkataramanan act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 8249daf8208SAnirudh Venkataramanan ICE_LG_ACT_VSI_LIST_ID_M; 8259daf8208SAnirudh Venkataramanan if (m_ent->vsi_count > 1) 8269daf8208SAnirudh Venkataramanan act |= ICE_LG_ACT_VSI_LIST; 8279daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[0] = cpu_to_le32(act); 8289daf8208SAnirudh Venkataramanan 8299daf8208SAnirudh Venkataramanan /* Second action descriptor type */ 8309daf8208SAnirudh Venkataramanan act = ICE_LG_ACT_GENERIC; 8319daf8208SAnirudh Venkataramanan 8329daf8208SAnirudh Venkataramanan act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 8339daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[1] = cpu_to_le32(act); 8349daf8208SAnirudh Venkataramanan 8354381147dSAnirudh Venkataramanan act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 8364381147dSAnirudh Venkataramanan ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 8379daf8208SAnirudh Venkataramanan 8389daf8208SAnirudh Venkataramanan /* Third action Marker value */ 8399daf8208SAnirudh Venkataramanan act |= ICE_LG_ACT_GENERIC; 8409daf8208SAnirudh Venkataramanan act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 8419daf8208SAnirudh Venkataramanan ICE_LG_ACT_GENERIC_VALUE_M; 8429daf8208SAnirudh Venkataramanan 8439daf8208SAnirudh Venkataramanan lg_act->pdata.lg_act.act[2] = cpu_to_le32(act); 8449daf8208SAnirudh Venkataramanan 8459daf8208SAnirudh Venkataramanan /* call the fill switch rule to fill the lookup tx rx structure */ 8469daf8208SAnirudh Venkataramanan ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 8479daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules); 8489daf8208SAnirudh Venkataramanan 8499daf8208SAnirudh Venkataramanan /* Update the action to point to the large action id */ 8509daf8208SAnirudh Venkataramanan rx_tx->pdata.lkup_tx_rx.act = 8519daf8208SAnirudh Venkataramanan cpu_to_le32(ICE_SINGLE_ACT_PTR | 8529daf8208SAnirudh Venkataramanan ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 8539daf8208SAnirudh Venkataramanan ICE_SINGLE_ACT_PTR_VAL_M)); 8549daf8208SAnirudh Venkataramanan 8559daf8208SAnirudh Venkataramanan /* Use the filter rule id of the previously created rule with single 8569daf8208SAnirudh Venkataramanan * act. Once the update happens, hardware will treat this as large 8579daf8208SAnirudh Venkataramanan * action 8589daf8208SAnirudh Venkataramanan */ 8599daf8208SAnirudh Venkataramanan rx_tx->pdata.lkup_tx_rx.index = 8609daf8208SAnirudh Venkataramanan cpu_to_le16(m_ent->fltr_info.fltr_rule_id); 8619daf8208SAnirudh Venkataramanan 8629daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 8639daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, NULL); 8649daf8208SAnirudh Venkataramanan if (!status) { 8659daf8208SAnirudh Venkataramanan m_ent->lg_act_idx = l_id; 8669daf8208SAnirudh Venkataramanan m_ent->sw_marker_id = sw_marker; 8679daf8208SAnirudh Venkataramanan } 8689daf8208SAnirudh Venkataramanan 8699daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), lg_act); 8709daf8208SAnirudh Venkataramanan return status; 8719daf8208SAnirudh Venkataramanan } 8729daf8208SAnirudh Venkataramanan 8739daf8208SAnirudh Venkataramanan /** 8749daf8208SAnirudh Venkataramanan * ice_create_vsi_list_map 8759daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 8765726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 8775726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 8789daf8208SAnirudh Venkataramanan * @vsi_list_id: VSI list id generated as part of allocate resource 8799daf8208SAnirudh Venkataramanan * 8809daf8208SAnirudh Venkataramanan * Helper function to create a new entry of VSI list id to VSI mapping 8819daf8208SAnirudh Venkataramanan * using the given VSI list id 8829daf8208SAnirudh Venkataramanan */ 8839daf8208SAnirudh Venkataramanan static struct ice_vsi_list_map_info * 8845726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 8859daf8208SAnirudh Venkataramanan u16 vsi_list_id) 8869daf8208SAnirudh Venkataramanan { 8879daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 8889daf8208SAnirudh Venkataramanan struct ice_vsi_list_map_info *v_map; 8899daf8208SAnirudh Venkataramanan int i; 8909daf8208SAnirudh Venkataramanan 8919daf8208SAnirudh Venkataramanan v_map = devm_kcalloc(ice_hw_to_dev(hw), 1, sizeof(*v_map), GFP_KERNEL); 8929daf8208SAnirudh Venkataramanan if (!v_map) 8939daf8208SAnirudh Venkataramanan return NULL; 8949daf8208SAnirudh Venkataramanan 8959daf8208SAnirudh Venkataramanan v_map->vsi_list_id = vsi_list_id; 8965726ca0eSAnirudh Venkataramanan v_map->ref_cnt = 1; 8979daf8208SAnirudh Venkataramanan for (i = 0; i < num_vsi; i++) 8985726ca0eSAnirudh Venkataramanan set_bit(vsi_handle_arr[i], v_map->vsi_map); 8999daf8208SAnirudh Venkataramanan 9009daf8208SAnirudh Venkataramanan list_add(&v_map->list_entry, &sw->vsi_list_map_head); 9019daf8208SAnirudh Venkataramanan return v_map; 9029daf8208SAnirudh Venkataramanan } 9039daf8208SAnirudh Venkataramanan 9049daf8208SAnirudh Venkataramanan /** 9059daf8208SAnirudh Venkataramanan * ice_update_vsi_list_rule 9069daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 9075726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to form a VSI list 9085726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 9099daf8208SAnirudh Venkataramanan * @vsi_list_id: VSI list id generated as part of allocate resource 9109daf8208SAnirudh Venkataramanan * @remove: Boolean value to indicate if this is a remove action 9119daf8208SAnirudh Venkataramanan * @opc: switch rules population command type - pass in the command opcode 9129daf8208SAnirudh Venkataramanan * @lkup_type: lookup type of the filter 9139daf8208SAnirudh Venkataramanan * 9149daf8208SAnirudh Venkataramanan * Call AQ command to add a new switch rule or update existing switch rule 9159daf8208SAnirudh Venkataramanan * using the given VSI list id 9169daf8208SAnirudh Venkataramanan */ 9179daf8208SAnirudh Venkataramanan static enum ice_status 9185726ca0eSAnirudh Venkataramanan ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 9199daf8208SAnirudh Venkataramanan u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 9209daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type) 9219daf8208SAnirudh Venkataramanan { 9229daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 9239daf8208SAnirudh Venkataramanan enum ice_status status; 9249daf8208SAnirudh Venkataramanan u16 s_rule_size; 9259daf8208SAnirudh Venkataramanan u16 type; 9269daf8208SAnirudh Venkataramanan int i; 9279daf8208SAnirudh Venkataramanan 9289daf8208SAnirudh Venkataramanan if (!num_vsi) 9299daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 9309daf8208SAnirudh Venkataramanan 9319daf8208SAnirudh Venkataramanan if (lkup_type == ICE_SW_LKUP_MAC || 9329daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_MAC_VLAN || 9339daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE || 9349daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 9359daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC || 9369daf8208SAnirudh Venkataramanan lkup_type == ICE_SW_LKUP_PROMISC_VLAN) 9379daf8208SAnirudh Venkataramanan type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 9389daf8208SAnirudh Venkataramanan ICE_AQC_SW_RULES_T_VSI_LIST_SET; 9399daf8208SAnirudh Venkataramanan else if (lkup_type == ICE_SW_LKUP_VLAN) 9409daf8208SAnirudh Venkataramanan type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 9419daf8208SAnirudh Venkataramanan ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 9429daf8208SAnirudh Venkataramanan else 9439daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 9449daf8208SAnirudh Venkataramanan 9459daf8208SAnirudh Venkataramanan s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi); 9469daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 9479daf8208SAnirudh Venkataramanan if (!s_rule) 9489daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 9495726ca0eSAnirudh Venkataramanan for (i = 0; i < num_vsi; i++) { 9505726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 9515726ca0eSAnirudh Venkataramanan status = ICE_ERR_PARAM; 9525726ca0eSAnirudh Venkataramanan goto exit; 9535726ca0eSAnirudh Venkataramanan } 9545726ca0eSAnirudh Venkataramanan /* AQ call requires hw_vsi_id(s) */ 9555726ca0eSAnirudh Venkataramanan s_rule->pdata.vsi_list.vsi[i] = 9565726ca0eSAnirudh Venkataramanan cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 9575726ca0eSAnirudh Venkataramanan } 9589daf8208SAnirudh Venkataramanan 9599daf8208SAnirudh Venkataramanan s_rule->type = cpu_to_le16(type); 9609daf8208SAnirudh Venkataramanan s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi); 9619daf8208SAnirudh Venkataramanan s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id); 9629daf8208SAnirudh Venkataramanan 9639daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 9649daf8208SAnirudh Venkataramanan 9655726ca0eSAnirudh Venkataramanan exit: 9669daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 9679daf8208SAnirudh Venkataramanan return status; 9689daf8208SAnirudh Venkataramanan } 9699daf8208SAnirudh Venkataramanan 9709daf8208SAnirudh Venkataramanan /** 9719daf8208SAnirudh Venkataramanan * ice_create_vsi_list_rule - Creates and populates a VSI list rule 9729daf8208SAnirudh Venkataramanan * @hw: pointer to the hw struct 9735726ca0eSAnirudh Venkataramanan * @vsi_handle_arr: array of VSI handles to form a VSI list 9745726ca0eSAnirudh Venkataramanan * @num_vsi: number of VSI handles in the array 9759daf8208SAnirudh Venkataramanan * @vsi_list_id: stores the ID of the VSI list to be created 9769daf8208SAnirudh Venkataramanan * @lkup_type: switch rule filter's lookup type 9779daf8208SAnirudh Venkataramanan */ 9789daf8208SAnirudh Venkataramanan static enum ice_status 9795726ca0eSAnirudh Venkataramanan ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 9809daf8208SAnirudh Venkataramanan u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 9819daf8208SAnirudh Venkataramanan { 9829daf8208SAnirudh Venkataramanan enum ice_status status; 9839daf8208SAnirudh Venkataramanan 9849daf8208SAnirudh Venkataramanan status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 9859daf8208SAnirudh Venkataramanan ice_aqc_opc_alloc_res); 9869daf8208SAnirudh Venkataramanan if (status) 9879daf8208SAnirudh Venkataramanan return status; 9889daf8208SAnirudh Venkataramanan 9899daf8208SAnirudh Venkataramanan /* Update the newly created VSI list to include the specified VSIs */ 9905726ca0eSAnirudh Venkataramanan return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 9915726ca0eSAnirudh Venkataramanan *vsi_list_id, false, 9925726ca0eSAnirudh Venkataramanan ice_aqc_opc_add_sw_rules, lkup_type); 9939daf8208SAnirudh Venkataramanan } 9949daf8208SAnirudh Venkataramanan 9959daf8208SAnirudh Venkataramanan /** 9969daf8208SAnirudh Venkataramanan * ice_create_pkt_fwd_rule 9979daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 9989daf8208SAnirudh Venkataramanan * @f_entry: entry containing packet forwarding information 9999daf8208SAnirudh Venkataramanan * 10009daf8208SAnirudh Venkataramanan * Create switch rule with given filter information and add an entry 10019daf8208SAnirudh Venkataramanan * to the corresponding filter management list to track this switch rule 10029daf8208SAnirudh Venkataramanan * and VSI mapping 10039daf8208SAnirudh Venkataramanan */ 10049daf8208SAnirudh Venkataramanan static enum ice_status 10059daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule(struct ice_hw *hw, 10069daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 10079daf8208SAnirudh Venkataramanan { 10089daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 10099daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 10109daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type l_type; 101180d144c9SAnirudh Venkataramanan struct ice_sw_recipe *recp; 10129daf8208SAnirudh Venkataramanan enum ice_status status; 10139daf8208SAnirudh Venkataramanan 10149daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 10159daf8208SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL); 10169daf8208SAnirudh Venkataramanan if (!s_rule) 10179daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 10189daf8208SAnirudh Venkataramanan fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry), 10199daf8208SAnirudh Venkataramanan GFP_KERNEL); 10209daf8208SAnirudh Venkataramanan if (!fm_entry) { 10219daf8208SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 10229daf8208SAnirudh Venkataramanan goto ice_create_pkt_fwd_rule_exit; 10239daf8208SAnirudh Venkataramanan } 10249daf8208SAnirudh Venkataramanan 10259daf8208SAnirudh Venkataramanan fm_entry->fltr_info = f_entry->fltr_info; 10269daf8208SAnirudh Venkataramanan 10279daf8208SAnirudh Venkataramanan /* Initialize all the fields for the management entry */ 10289daf8208SAnirudh Venkataramanan fm_entry->vsi_count = 1; 10299daf8208SAnirudh Venkataramanan fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 10309daf8208SAnirudh Venkataramanan fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 10319daf8208SAnirudh Venkataramanan fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 10329daf8208SAnirudh Venkataramanan 10339daf8208SAnirudh Venkataramanan ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 10349daf8208SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules); 10359daf8208SAnirudh Venkataramanan 10369daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 10379daf8208SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules, NULL); 10389daf8208SAnirudh Venkataramanan if (status) { 10399daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), fm_entry); 10409daf8208SAnirudh Venkataramanan goto ice_create_pkt_fwd_rule_exit; 10419daf8208SAnirudh Venkataramanan } 10429daf8208SAnirudh Venkataramanan 10439daf8208SAnirudh Venkataramanan f_entry->fltr_info.fltr_rule_id = 10449daf8208SAnirudh Venkataramanan le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 10459daf8208SAnirudh Venkataramanan fm_entry->fltr_info.fltr_rule_id = 10469daf8208SAnirudh Venkataramanan le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 10479daf8208SAnirudh Venkataramanan 10489daf8208SAnirudh Venkataramanan /* The book keeping entries will get removed when base driver 10499daf8208SAnirudh Venkataramanan * calls remove filter AQ command 10509daf8208SAnirudh Venkataramanan */ 10519daf8208SAnirudh Venkataramanan l_type = fm_entry->fltr_info.lkup_type; 105280d144c9SAnirudh Venkataramanan recp = &hw->switch_info->recp_list[l_type]; 105380d144c9SAnirudh Venkataramanan list_add(&fm_entry->list_entry, &recp->filt_rules); 105480d144c9SAnirudh Venkataramanan 10559daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule_exit: 10569daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 10579daf8208SAnirudh Venkataramanan return status; 10589daf8208SAnirudh Venkataramanan } 10599daf8208SAnirudh Venkataramanan 10609daf8208SAnirudh Venkataramanan /** 10619daf8208SAnirudh Venkataramanan * ice_update_pkt_fwd_rule 10629daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 106380d144c9SAnirudh Venkataramanan * @f_info: filter information for switch rule 10649daf8208SAnirudh Venkataramanan * 10659daf8208SAnirudh Venkataramanan * Call AQ command to update a previously created switch rule with a 10669daf8208SAnirudh Venkataramanan * VSI list id 10679daf8208SAnirudh Venkataramanan */ 10689daf8208SAnirudh Venkataramanan static enum ice_status 106980d144c9SAnirudh Venkataramanan ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 10709daf8208SAnirudh Venkataramanan { 10719daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 10729daf8208SAnirudh Venkataramanan enum ice_status status; 10739daf8208SAnirudh Venkataramanan 10749daf8208SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 10759daf8208SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL); 10769daf8208SAnirudh Venkataramanan if (!s_rule) 10779daf8208SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 10789daf8208SAnirudh Venkataramanan 107980d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 10809daf8208SAnirudh Venkataramanan 108180d144c9SAnirudh Venkataramanan s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(f_info->fltr_rule_id); 10829daf8208SAnirudh Venkataramanan 10839daf8208SAnirudh Venkataramanan /* Update switch rule with new rule set to forward VSI list */ 10849daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 10859daf8208SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, NULL); 10869daf8208SAnirudh Venkataramanan 10879daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 10889daf8208SAnirudh Venkataramanan return status; 10899daf8208SAnirudh Venkataramanan } 10909daf8208SAnirudh Venkataramanan 10919daf8208SAnirudh Venkataramanan /** 1092b1edc14aSMd Fahad Iqbal Polash * ice_update_sw_rule_bridge_mode 1093b1edc14aSMd Fahad Iqbal Polash * @hw: pointer to the hw struct 1094b1edc14aSMd Fahad Iqbal Polash * 1095b1edc14aSMd Fahad Iqbal Polash * Updates unicast switch filter rules based on VEB/VEPA mode 1096b1edc14aSMd Fahad Iqbal Polash */ 1097b1edc14aSMd Fahad Iqbal Polash enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 1098b1edc14aSMd Fahad Iqbal Polash { 1099b1edc14aSMd Fahad Iqbal Polash struct ice_switch_info *sw = hw->switch_info; 1100b1edc14aSMd Fahad Iqbal Polash struct ice_fltr_mgmt_list_entry *fm_entry; 1101b1edc14aSMd Fahad Iqbal Polash enum ice_status status = 0; 1102b1edc14aSMd Fahad Iqbal Polash struct list_head *rule_head; 1103b1edc14aSMd Fahad Iqbal Polash struct mutex *rule_lock; /* Lock to protect filter rule list */ 1104b1edc14aSMd Fahad Iqbal Polash 1105b1edc14aSMd Fahad Iqbal Polash rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 1106b1edc14aSMd Fahad Iqbal Polash rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 1107b1edc14aSMd Fahad Iqbal Polash 1108b1edc14aSMd Fahad Iqbal Polash mutex_lock(rule_lock); 1109b1edc14aSMd Fahad Iqbal Polash list_for_each_entry(fm_entry, rule_head, list_entry) { 1110b1edc14aSMd Fahad Iqbal Polash struct ice_fltr_info *fi = &fm_entry->fltr_info; 1111b1edc14aSMd Fahad Iqbal Polash u8 *addr = fi->l_data.mac.mac_addr; 1112b1edc14aSMd Fahad Iqbal Polash 1113b1edc14aSMd Fahad Iqbal Polash /* Update unicast Tx rules to reflect the selected 1114b1edc14aSMd Fahad Iqbal Polash * VEB/VEPA mode 1115b1edc14aSMd Fahad Iqbal Polash */ 1116b1edc14aSMd Fahad Iqbal Polash if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) && 1117b1edc14aSMd Fahad Iqbal Polash (fi->fltr_act == ICE_FWD_TO_VSI || 1118b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1119b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_Q || 1120b1edc14aSMd Fahad Iqbal Polash fi->fltr_act == ICE_FWD_TO_QGRP)) { 1121b1edc14aSMd Fahad Iqbal Polash status = ice_update_pkt_fwd_rule(hw, fi); 1122b1edc14aSMd Fahad Iqbal Polash if (status) 1123b1edc14aSMd Fahad Iqbal Polash break; 1124b1edc14aSMd Fahad Iqbal Polash } 1125b1edc14aSMd Fahad Iqbal Polash } 1126b1edc14aSMd Fahad Iqbal Polash 1127b1edc14aSMd Fahad Iqbal Polash mutex_unlock(rule_lock); 1128b1edc14aSMd Fahad Iqbal Polash 1129b1edc14aSMd Fahad Iqbal Polash return status; 1130b1edc14aSMd Fahad Iqbal Polash } 1131b1edc14aSMd Fahad Iqbal Polash 1132b1edc14aSMd Fahad Iqbal Polash /** 113380d144c9SAnirudh Venkataramanan * ice_add_update_vsi_list 11349daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 11359daf8208SAnirudh Venkataramanan * @m_entry: pointer to current filter management list entry 11369daf8208SAnirudh Venkataramanan * @cur_fltr: filter information from the book keeping entry 11379daf8208SAnirudh Venkataramanan * @new_fltr: filter information with the new VSI to be added 11389daf8208SAnirudh Venkataramanan * 11399daf8208SAnirudh Venkataramanan * Call AQ command to add or update previously created VSI list with new VSI. 11409daf8208SAnirudh Venkataramanan * 11419daf8208SAnirudh Venkataramanan * Helper function to do book keeping associated with adding filter information 11429daf8208SAnirudh Venkataramanan * The algorithm to do the booking keeping is described below : 11439daf8208SAnirudh Venkataramanan * When a VSI needs to subscribe to a given filter( MAC/VLAN/Ethtype etc.) 11449daf8208SAnirudh Venkataramanan * if only one VSI has been added till now 11459daf8208SAnirudh Venkataramanan * Allocate a new VSI list and add two VSIs 11469daf8208SAnirudh Venkataramanan * to this list using switch rule command 11479daf8208SAnirudh Venkataramanan * Update the previously created switch rule with the 11489daf8208SAnirudh Venkataramanan * newly created VSI list id 11499daf8208SAnirudh Venkataramanan * if a VSI list was previously created 11509daf8208SAnirudh Venkataramanan * Add the new VSI to the previously created VSI list set 11519daf8208SAnirudh Venkataramanan * using the update switch rule command 11529daf8208SAnirudh Venkataramanan */ 11539daf8208SAnirudh Venkataramanan static enum ice_status 115480d144c9SAnirudh Venkataramanan ice_add_update_vsi_list(struct ice_hw *hw, 11559daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *m_entry, 11569daf8208SAnirudh Venkataramanan struct ice_fltr_info *cur_fltr, 11579daf8208SAnirudh Venkataramanan struct ice_fltr_info *new_fltr) 11589daf8208SAnirudh Venkataramanan { 11599daf8208SAnirudh Venkataramanan enum ice_status status = 0; 11609daf8208SAnirudh Venkataramanan u16 vsi_list_id = 0; 11619daf8208SAnirudh Venkataramanan 11629daf8208SAnirudh Venkataramanan if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 11639daf8208SAnirudh Venkataramanan cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 11649daf8208SAnirudh Venkataramanan return ICE_ERR_NOT_IMPL; 11659daf8208SAnirudh Venkataramanan 11669daf8208SAnirudh Venkataramanan if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 11679daf8208SAnirudh Venkataramanan new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 11689daf8208SAnirudh Venkataramanan (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 11699daf8208SAnirudh Venkataramanan cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 11709daf8208SAnirudh Venkataramanan return ICE_ERR_NOT_IMPL; 11719daf8208SAnirudh Venkataramanan 11729daf8208SAnirudh Venkataramanan if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 11739daf8208SAnirudh Venkataramanan /* Only one entry existed in the mapping and it was not already 11749daf8208SAnirudh Venkataramanan * a part of a VSI list. So, create a VSI list with the old and 11759daf8208SAnirudh Venkataramanan * new VSIs. 11769daf8208SAnirudh Venkataramanan */ 117780d144c9SAnirudh Venkataramanan struct ice_fltr_info tmp_fltr; 11785726ca0eSAnirudh Venkataramanan u16 vsi_handle_arr[2]; 11799daf8208SAnirudh Venkataramanan 11809daf8208SAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 11815726ca0eSAnirudh Venkataramanan if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 11829daf8208SAnirudh Venkataramanan return ICE_ERR_ALREADY_EXISTS; 11839daf8208SAnirudh Venkataramanan 11845726ca0eSAnirudh Venkataramanan vsi_handle_arr[0] = cur_fltr->vsi_handle; 11855726ca0eSAnirudh Venkataramanan vsi_handle_arr[1] = new_fltr->vsi_handle; 11865726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 11879daf8208SAnirudh Venkataramanan &vsi_list_id, 11889daf8208SAnirudh Venkataramanan new_fltr->lkup_type); 11899daf8208SAnirudh Venkataramanan if (status) 11909daf8208SAnirudh Venkataramanan return status; 11919daf8208SAnirudh Venkataramanan 119280d144c9SAnirudh Venkataramanan tmp_fltr = *new_fltr; 119380d144c9SAnirudh Venkataramanan tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 119480d144c9SAnirudh Venkataramanan tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 119580d144c9SAnirudh Venkataramanan tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 11969daf8208SAnirudh Venkataramanan /* Update the previous switch rule of "MAC forward to VSI" to 11979daf8208SAnirudh Venkataramanan * "MAC fwd to VSI list" 11989daf8208SAnirudh Venkataramanan */ 119980d144c9SAnirudh Venkataramanan status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 12009daf8208SAnirudh Venkataramanan if (status) 12019daf8208SAnirudh Venkataramanan return status; 12029daf8208SAnirudh Venkataramanan 12039daf8208SAnirudh Venkataramanan cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 12049daf8208SAnirudh Venkataramanan cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 12059daf8208SAnirudh Venkataramanan m_entry->vsi_list_info = 12065726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 12079daf8208SAnirudh Venkataramanan vsi_list_id); 12089daf8208SAnirudh Venkataramanan 12099daf8208SAnirudh Venkataramanan /* If this entry was large action then the large action needs 12109daf8208SAnirudh Venkataramanan * to be updated to point to FWD to VSI list 12119daf8208SAnirudh Venkataramanan */ 12129daf8208SAnirudh Venkataramanan if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 12139daf8208SAnirudh Venkataramanan status = 12149daf8208SAnirudh Venkataramanan ice_add_marker_act(hw, m_entry, 12159daf8208SAnirudh Venkataramanan m_entry->sw_marker_id, 12169daf8208SAnirudh Venkataramanan m_entry->lg_act_idx); 12179daf8208SAnirudh Venkataramanan } else { 12185726ca0eSAnirudh Venkataramanan u16 vsi_handle = new_fltr->vsi_handle; 12199daf8208SAnirudh Venkataramanan enum ice_adminq_opc opcode; 12209daf8208SAnirudh Venkataramanan 12219daf8208SAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 12225726ca0eSAnirudh Venkataramanan if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map)) 12239daf8208SAnirudh Venkataramanan return 0; 12249daf8208SAnirudh Venkataramanan 12259daf8208SAnirudh Venkataramanan /* Update the previously created VSI list set with 12269daf8208SAnirudh Venkataramanan * the new VSI id passed in 12279daf8208SAnirudh Venkataramanan */ 12289daf8208SAnirudh Venkataramanan vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 12299daf8208SAnirudh Venkataramanan opcode = ice_aqc_opc_update_sw_rules; 12309daf8208SAnirudh Venkataramanan 12315726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 12325726ca0eSAnirudh Venkataramanan vsi_list_id, false, opcode, 12339daf8208SAnirudh Venkataramanan new_fltr->lkup_type); 12349daf8208SAnirudh Venkataramanan /* update VSI list mapping info with new VSI id */ 12359daf8208SAnirudh Venkataramanan if (!status) 12365726ca0eSAnirudh Venkataramanan set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map); 12379daf8208SAnirudh Venkataramanan } 12389daf8208SAnirudh Venkataramanan if (!status) 12399daf8208SAnirudh Venkataramanan m_entry->vsi_count++; 12409daf8208SAnirudh Venkataramanan return status; 12419daf8208SAnirudh Venkataramanan } 12429daf8208SAnirudh Venkataramanan 12439daf8208SAnirudh Venkataramanan /** 124480d144c9SAnirudh Venkataramanan * ice_find_rule_entry - Search a rule entry 12459daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 124680d144c9SAnirudh Venkataramanan * @recp_id: lookup type for which the specified rule needs to be searched 124780d144c9SAnirudh Venkataramanan * @f_info: rule information 12489daf8208SAnirudh Venkataramanan * 124980d144c9SAnirudh Venkataramanan * Helper function to search for a given rule entry 125080d144c9SAnirudh Venkataramanan * Returns pointer to entry storing the rule if found 12519daf8208SAnirudh Venkataramanan */ 12529daf8208SAnirudh Venkataramanan static struct ice_fltr_mgmt_list_entry * 125380d144c9SAnirudh Venkataramanan ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info) 12549daf8208SAnirudh Venkataramanan { 125580d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 12569daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 125780d144c9SAnirudh Venkataramanan struct list_head *list_head; 12589daf8208SAnirudh Venkataramanan 125980d144c9SAnirudh Venkataramanan list_head = &sw->recp_list[recp_id].filt_rules; 126080d144c9SAnirudh Venkataramanan list_for_each_entry(list_itr, list_head, list_entry) { 126180d144c9SAnirudh Venkataramanan if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 126280d144c9SAnirudh Venkataramanan sizeof(f_info->l_data)) && 126380d144c9SAnirudh Venkataramanan f_info->flag == list_itr->fltr_info.flag) { 126480d144c9SAnirudh Venkataramanan ret = list_itr; 12659daf8208SAnirudh Venkataramanan break; 12669daf8208SAnirudh Venkataramanan } 12679daf8208SAnirudh Venkataramanan } 126880d144c9SAnirudh Venkataramanan return ret; 12699daf8208SAnirudh Venkataramanan } 12709daf8208SAnirudh Venkataramanan 12719daf8208SAnirudh Venkataramanan /** 12725726ca0eSAnirudh Venkataramanan * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 12735726ca0eSAnirudh Venkataramanan * @hw: pointer to the hardware structure 12745726ca0eSAnirudh Venkataramanan * @recp_id: lookup type for which VSI lists needs to be searched 12755726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to be found in VSI list 12765726ca0eSAnirudh Venkataramanan * @vsi_list_id: VSI list id found containing vsi_handle 12775726ca0eSAnirudh Venkataramanan * 12785726ca0eSAnirudh Venkataramanan * Helper function to search a VSI list with single entry containing given VSI 12795726ca0eSAnirudh Venkataramanan * handle element. This can be extended further to search VSI list with more 12805726ca0eSAnirudh Venkataramanan * than 1 vsi_count. Returns pointer to VSI list entry if found. 12815726ca0eSAnirudh Venkataramanan */ 12825726ca0eSAnirudh Venkataramanan static struct ice_vsi_list_map_info * 12835726ca0eSAnirudh Venkataramanan ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, 12845726ca0eSAnirudh Venkataramanan u16 *vsi_list_id) 12855726ca0eSAnirudh Venkataramanan { 12865726ca0eSAnirudh Venkataramanan struct ice_vsi_list_map_info *map_info = NULL; 12875726ca0eSAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 12885726ca0eSAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_itr; 12895726ca0eSAnirudh Venkataramanan struct list_head *list_head; 12905726ca0eSAnirudh Venkataramanan 12915726ca0eSAnirudh Venkataramanan list_head = &sw->recp_list[recp_id].filt_rules; 12925726ca0eSAnirudh Venkataramanan list_for_each_entry(list_itr, list_head, list_entry) { 12935726ca0eSAnirudh Venkataramanan if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) { 12945726ca0eSAnirudh Venkataramanan map_info = list_itr->vsi_list_info; 12955726ca0eSAnirudh Venkataramanan if (test_bit(vsi_handle, map_info->vsi_map)) { 12965726ca0eSAnirudh Venkataramanan *vsi_list_id = map_info->vsi_list_id; 12975726ca0eSAnirudh Venkataramanan return map_info; 12985726ca0eSAnirudh Venkataramanan } 12995726ca0eSAnirudh Venkataramanan } 13005726ca0eSAnirudh Venkataramanan } 13015726ca0eSAnirudh Venkataramanan return NULL; 13025726ca0eSAnirudh Venkataramanan } 13035726ca0eSAnirudh Venkataramanan 13045726ca0eSAnirudh Venkataramanan /** 130580d144c9SAnirudh Venkataramanan * ice_add_rule_internal - add rule for a given lookup type 13069daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 130780d144c9SAnirudh Venkataramanan * @recp_id: lookup type (recipe id) for which rule has to be added 13089daf8208SAnirudh Venkataramanan * @f_entry: structure containing MAC forwarding information 13099daf8208SAnirudh Venkataramanan * 131080d144c9SAnirudh Venkataramanan * Adds or updates the rule lists for a given recipe 13119daf8208SAnirudh Venkataramanan */ 13129daf8208SAnirudh Venkataramanan static enum ice_status 131380d144c9SAnirudh Venkataramanan ice_add_rule_internal(struct ice_hw *hw, u8 recp_id, 131480d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 13159daf8208SAnirudh Venkataramanan { 131680d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 13179daf8208SAnirudh Venkataramanan struct ice_fltr_info *new_fltr, *cur_fltr; 13189daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *m_entry; 131980d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 132080d144c9SAnirudh Venkataramanan enum ice_status status = 0; 13219daf8208SAnirudh Venkataramanan 13225726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 13235726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 13245726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 13255726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 13265726ca0eSAnirudh Venkataramanan 132780d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 132880d144c9SAnirudh Venkataramanan 132980d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 13309daf8208SAnirudh Venkataramanan new_fltr = &f_entry->fltr_info; 133180d144c9SAnirudh Venkataramanan if (new_fltr->flag & ICE_FLTR_RX) 133280d144c9SAnirudh Venkataramanan new_fltr->src = hw->port_info->lport; 133380d144c9SAnirudh Venkataramanan else if (new_fltr->flag & ICE_FLTR_TX) 13345726ca0eSAnirudh Venkataramanan new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id; 13359daf8208SAnirudh Venkataramanan 133680d144c9SAnirudh Venkataramanan m_entry = ice_find_rule_entry(hw, recp_id, new_fltr); 133780d144c9SAnirudh Venkataramanan if (!m_entry) { 133880d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 13399daf8208SAnirudh Venkataramanan return ice_create_pkt_fwd_rule(hw, f_entry); 134080d144c9SAnirudh Venkataramanan } 13419daf8208SAnirudh Venkataramanan 13429daf8208SAnirudh Venkataramanan cur_fltr = &m_entry->fltr_info; 134380d144c9SAnirudh Venkataramanan status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 134480d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 13459daf8208SAnirudh Venkataramanan 134680d144c9SAnirudh Venkataramanan return status; 134780d144c9SAnirudh Venkataramanan } 134880d144c9SAnirudh Venkataramanan 134980d144c9SAnirudh Venkataramanan /** 135080d144c9SAnirudh Venkataramanan * ice_remove_vsi_list_rule 135180d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 135280d144c9SAnirudh Venkataramanan * @vsi_list_id: VSI list id generated as part of allocate resource 135380d144c9SAnirudh Venkataramanan * @lkup_type: switch rule filter lookup type 135480d144c9SAnirudh Venkataramanan * 135580d144c9SAnirudh Venkataramanan * The VSI list should be emptied before this function is called to remove the 135680d144c9SAnirudh Venkataramanan * VSI list. 135780d144c9SAnirudh Venkataramanan */ 135880d144c9SAnirudh Venkataramanan static enum ice_status 135980d144c9SAnirudh Venkataramanan ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 136080d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type) 136180d144c9SAnirudh Venkataramanan { 136280d144c9SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 136380d144c9SAnirudh Venkataramanan enum ice_status status; 136480d144c9SAnirudh Venkataramanan u16 s_rule_size; 136580d144c9SAnirudh Venkataramanan 136680d144c9SAnirudh Venkataramanan s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0); 136780d144c9SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 136880d144c9SAnirudh Venkataramanan if (!s_rule) 136980d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 137080d144c9SAnirudh Venkataramanan 137180d144c9SAnirudh Venkataramanan s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR); 137280d144c9SAnirudh Venkataramanan s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id); 137380d144c9SAnirudh Venkataramanan 137480d144c9SAnirudh Venkataramanan /* Free the vsi_list resource that we allocated. It is assumed that the 137580d144c9SAnirudh Venkataramanan * list is empty at this point. 137680d144c9SAnirudh Venkataramanan */ 137780d144c9SAnirudh Venkataramanan status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 137880d144c9SAnirudh Venkataramanan ice_aqc_opc_free_res); 137980d144c9SAnirudh Venkataramanan 138080d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 138180d144c9SAnirudh Venkataramanan return status; 138280d144c9SAnirudh Venkataramanan } 138380d144c9SAnirudh Venkataramanan 138480d144c9SAnirudh Venkataramanan /** 138580d144c9SAnirudh Venkataramanan * ice_rem_update_vsi_list 138680d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 13875726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle of the VSI to remove 138880d144c9SAnirudh Venkataramanan * @fm_list: filter management entry for which the VSI list management needs to 138980d144c9SAnirudh Venkataramanan * be done 139080d144c9SAnirudh Venkataramanan */ 139180d144c9SAnirudh Venkataramanan static enum ice_status 13925726ca0eSAnirudh Venkataramanan ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 139380d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_list) 139480d144c9SAnirudh Venkataramanan { 139580d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type; 139680d144c9SAnirudh Venkataramanan enum ice_status status = 0; 139780d144c9SAnirudh Venkataramanan u16 vsi_list_id; 139880d144c9SAnirudh Venkataramanan 139980d144c9SAnirudh Venkataramanan if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 140080d144c9SAnirudh Venkataramanan fm_list->vsi_count == 0) 140180d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 140280d144c9SAnirudh Venkataramanan 140380d144c9SAnirudh Venkataramanan /* A rule with the VSI being removed does not exist */ 14045726ca0eSAnirudh Venkataramanan if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map)) 140580d144c9SAnirudh Venkataramanan return ICE_ERR_DOES_NOT_EXIST; 140680d144c9SAnirudh Venkataramanan 140780d144c9SAnirudh Venkataramanan lkup_type = fm_list->fltr_info.lkup_type; 140880d144c9SAnirudh Venkataramanan vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 14095726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 141080d144c9SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, 141180d144c9SAnirudh Venkataramanan lkup_type); 141280d144c9SAnirudh Venkataramanan if (status) 141380d144c9SAnirudh Venkataramanan return status; 141480d144c9SAnirudh Venkataramanan 141580d144c9SAnirudh Venkataramanan fm_list->vsi_count--; 14165726ca0eSAnirudh Venkataramanan clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 141780d144c9SAnirudh Venkataramanan 141880d144c9SAnirudh Venkataramanan if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 141980d144c9SAnirudh Venkataramanan (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 142080d144c9SAnirudh Venkataramanan struct ice_vsi_list_map_info *vsi_list_info = 142180d144c9SAnirudh Venkataramanan fm_list->vsi_list_info; 14225726ca0eSAnirudh Venkataramanan u16 rem_vsi_handle; 142380d144c9SAnirudh Venkataramanan 14245726ca0eSAnirudh Venkataramanan rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map, 142580d144c9SAnirudh Venkataramanan ICE_MAX_VSI); 14265726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 142780d144c9SAnirudh Venkataramanan return ICE_ERR_OUT_OF_RANGE; 14285726ca0eSAnirudh Venkataramanan status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 142980d144c9SAnirudh Venkataramanan vsi_list_id, true, 143080d144c9SAnirudh Venkataramanan ice_aqc_opc_update_sw_rules, 143180d144c9SAnirudh Venkataramanan lkup_type); 143280d144c9SAnirudh Venkataramanan if (status) 143380d144c9SAnirudh Venkataramanan return status; 143480d144c9SAnirudh Venkataramanan 143580d144c9SAnirudh Venkataramanan /* Remove the VSI list since it is no longer used */ 143680d144c9SAnirudh Venkataramanan status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 143780d144c9SAnirudh Venkataramanan if (status) 143880d144c9SAnirudh Venkataramanan return status; 143980d144c9SAnirudh Venkataramanan 144080d144c9SAnirudh Venkataramanan /* Change the list entry action from VSI_LIST to VSI */ 144180d144c9SAnirudh Venkataramanan fm_list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 14425726ca0eSAnirudh Venkataramanan fm_list->fltr_info.fwd_id.hw_vsi_id = 14435726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, rem_vsi_handle); 14445726ca0eSAnirudh Venkataramanan fm_list->fltr_info.vsi_handle = rem_vsi_handle; 144580d144c9SAnirudh Venkataramanan 144680d144c9SAnirudh Venkataramanan list_del(&vsi_list_info->list_entry); 144780d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), vsi_list_info); 144880d144c9SAnirudh Venkataramanan fm_list->vsi_list_info = NULL; 144980d144c9SAnirudh Venkataramanan } 145080d144c9SAnirudh Venkataramanan 145180d144c9SAnirudh Venkataramanan return status; 145280d144c9SAnirudh Venkataramanan } 145380d144c9SAnirudh Venkataramanan 145480d144c9SAnirudh Venkataramanan /** 145580d144c9SAnirudh Venkataramanan * ice_remove_rule_internal - Remove a filter rule of a given type 145680d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 145780d144c9SAnirudh Venkataramanan * @recp_id: recipe id for which the rule needs to removed 145880d144c9SAnirudh Venkataramanan * @f_entry: rule entry containing filter information 145980d144c9SAnirudh Venkataramanan */ 146080d144c9SAnirudh Venkataramanan static enum ice_status 146180d144c9SAnirudh Venkataramanan ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id, 146280d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *f_entry) 146380d144c9SAnirudh Venkataramanan { 146480d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 146580d144c9SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *list_elem; 146680d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 146780d144c9SAnirudh Venkataramanan enum ice_status status = 0; 146880d144c9SAnirudh Venkataramanan bool remove_rule = false; 14695726ca0eSAnirudh Venkataramanan u16 vsi_handle; 14705726ca0eSAnirudh Venkataramanan 14715726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 14725726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 14735726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 14745726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 147580d144c9SAnirudh Venkataramanan 147680d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 147780d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 147880d144c9SAnirudh Venkataramanan list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info); 147980d144c9SAnirudh Venkataramanan if (!list_elem) { 148080d144c9SAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 148180d144c9SAnirudh Venkataramanan goto exit; 148280d144c9SAnirudh Venkataramanan } 148380d144c9SAnirudh Venkataramanan 148480d144c9SAnirudh Venkataramanan if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 148580d144c9SAnirudh Venkataramanan remove_rule = true; 14865726ca0eSAnirudh Venkataramanan } else if (!list_elem->vsi_list_info) { 14875726ca0eSAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 14885726ca0eSAnirudh Venkataramanan goto exit; 148980d144c9SAnirudh Venkataramanan } else { 14905726ca0eSAnirudh Venkataramanan if (list_elem->vsi_list_info->ref_cnt > 1) 14915726ca0eSAnirudh Venkataramanan list_elem->vsi_list_info->ref_cnt--; 14925726ca0eSAnirudh Venkataramanan vsi_handle = f_entry->fltr_info.vsi_handle; 14935726ca0eSAnirudh Venkataramanan status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 149480d144c9SAnirudh Venkataramanan if (status) 149580d144c9SAnirudh Venkataramanan goto exit; 149680d144c9SAnirudh Venkataramanan /* if vsi count goes to zero after updating the vsi list */ 149780d144c9SAnirudh Venkataramanan if (list_elem->vsi_count == 0) 149880d144c9SAnirudh Venkataramanan remove_rule = true; 149980d144c9SAnirudh Venkataramanan } 150080d144c9SAnirudh Venkataramanan 150180d144c9SAnirudh Venkataramanan if (remove_rule) { 150280d144c9SAnirudh Venkataramanan /* Remove the lookup rule */ 150380d144c9SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 150480d144c9SAnirudh Venkataramanan 150580d144c9SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), 150680d144c9SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 150780d144c9SAnirudh Venkataramanan GFP_KERNEL); 150880d144c9SAnirudh Venkataramanan if (!s_rule) { 150980d144c9SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 151080d144c9SAnirudh Venkataramanan goto exit; 151180d144c9SAnirudh Venkataramanan } 151280d144c9SAnirudh Venkataramanan 151380d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 151480d144c9SAnirudh Venkataramanan ice_aqc_opc_remove_sw_rules); 151580d144c9SAnirudh Venkataramanan 151680d144c9SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, 151780d144c9SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1, 151880d144c9SAnirudh Venkataramanan ice_aqc_opc_remove_sw_rules, NULL); 151980d144c9SAnirudh Venkataramanan if (status) 152080d144c9SAnirudh Venkataramanan goto exit; 152180d144c9SAnirudh Venkataramanan 152280d144c9SAnirudh Venkataramanan /* Remove a book keeping from the list */ 152380d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 152480d144c9SAnirudh Venkataramanan 152580d144c9SAnirudh Venkataramanan list_del(&list_elem->list_entry); 152680d144c9SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), list_elem); 152780d144c9SAnirudh Venkataramanan } 152880d144c9SAnirudh Venkataramanan exit: 152980d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 153080d144c9SAnirudh Venkataramanan return status; 15319daf8208SAnirudh Venkataramanan } 15329daf8208SAnirudh Venkataramanan 15339daf8208SAnirudh Venkataramanan /** 15349daf8208SAnirudh Venkataramanan * ice_add_mac - Add a MAC address based filter rule 15359daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 15369daf8208SAnirudh Venkataramanan * @m_list: list of MAC addresses and forwarding information 15379daf8208SAnirudh Venkataramanan * 15389daf8208SAnirudh Venkataramanan * IMPORTANT: When the ucast_shared flag is set to false and m_list has 15399daf8208SAnirudh Venkataramanan * multiple unicast addresses, the function assumes that all the 15409daf8208SAnirudh Venkataramanan * addresses are unique in a given add_mac call. It doesn't 15419daf8208SAnirudh Venkataramanan * check for duplicates in this case, removing duplicates from a given 15429daf8208SAnirudh Venkataramanan * list should be taken care of in the caller of this function. 15439daf8208SAnirudh Venkataramanan */ 15449daf8208SAnirudh Venkataramanan enum ice_status 15459daf8208SAnirudh Venkataramanan ice_add_mac(struct ice_hw *hw, struct list_head *m_list) 15469daf8208SAnirudh Venkataramanan { 15479daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule, *r_iter; 15489daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *m_list_itr; 154980d144c9SAnirudh Venkataramanan struct list_head *rule_head; 15509daf8208SAnirudh Venkataramanan u16 elem_sent, total_elem_left; 155180d144c9SAnirudh Venkataramanan struct ice_switch_info *sw; 155280d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 15539daf8208SAnirudh Venkataramanan enum ice_status status = 0; 15549daf8208SAnirudh Venkataramanan u16 num_unicast = 0; 15559daf8208SAnirudh Venkataramanan u16 s_rule_size; 15569daf8208SAnirudh Venkataramanan 15579daf8208SAnirudh Venkataramanan if (!m_list || !hw) 15589daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 15599daf8208SAnirudh Venkataramanan 156080d144c9SAnirudh Venkataramanan s_rule = NULL; 156180d144c9SAnirudh Venkataramanan sw = hw->switch_info; 156280d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 15639daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 15649daf8208SAnirudh Venkataramanan u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 15655726ca0eSAnirudh Venkataramanan u16 vsi_handle; 15665726ca0eSAnirudh Venkataramanan u16 hw_vsi_id; 15679daf8208SAnirudh Venkataramanan 156880d144c9SAnirudh Venkataramanan m_list_itr->fltr_info.flag = ICE_FLTR_TX; 15695726ca0eSAnirudh Venkataramanan vsi_handle = m_list_itr->fltr_info.vsi_handle; 15705726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 15715726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 15725726ca0eSAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 15735726ca0eSAnirudh Venkataramanan m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 15745726ca0eSAnirudh Venkataramanan /* update the src in case it is vsi num */ 15755726ca0eSAnirudh Venkataramanan if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 15765726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 15775726ca0eSAnirudh Venkataramanan m_list_itr->fltr_info.src = hw_vsi_id; 157880d144c9SAnirudh Venkataramanan if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 157980d144c9SAnirudh Venkataramanan is_zero_ether_addr(add)) 15809daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 15819daf8208SAnirudh Venkataramanan if (is_unicast_ether_addr(add) && !hw->ucast_shared) { 15829daf8208SAnirudh Venkataramanan /* Don't overwrite the unicast address */ 158380d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 158480d144c9SAnirudh Venkataramanan if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, 158580d144c9SAnirudh Venkataramanan &m_list_itr->fltr_info)) { 158680d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 15879daf8208SAnirudh Venkataramanan return ICE_ERR_ALREADY_EXISTS; 158880d144c9SAnirudh Venkataramanan } 158980d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 15909daf8208SAnirudh Venkataramanan num_unicast++; 15919daf8208SAnirudh Venkataramanan } else if (is_multicast_ether_addr(add) || 15929daf8208SAnirudh Venkataramanan (is_unicast_ether_addr(add) && hw->ucast_shared)) { 159380d144c9SAnirudh Venkataramanan m_list_itr->status = 159480d144c9SAnirudh Venkataramanan ice_add_rule_internal(hw, ICE_SW_LKUP_MAC, 159580d144c9SAnirudh Venkataramanan m_list_itr); 159680d144c9SAnirudh Venkataramanan if (m_list_itr->status) 159780d144c9SAnirudh Venkataramanan return m_list_itr->status; 15989daf8208SAnirudh Venkataramanan } 15999daf8208SAnirudh Venkataramanan } 16009daf8208SAnirudh Venkataramanan 160180d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 16029daf8208SAnirudh Venkataramanan /* Exit if no suitable entries were found for adding bulk switch rule */ 160380d144c9SAnirudh Venkataramanan if (!num_unicast) { 160480d144c9SAnirudh Venkataramanan status = 0; 160580d144c9SAnirudh Venkataramanan goto ice_add_mac_exit; 160680d144c9SAnirudh Venkataramanan } 160780d144c9SAnirudh Venkataramanan 160880d144c9SAnirudh Venkataramanan rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 16099daf8208SAnirudh Venkataramanan 16109daf8208SAnirudh Venkataramanan /* Allocate switch rule buffer for the bulk update for unicast */ 16119daf8208SAnirudh Venkataramanan s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 16129daf8208SAnirudh Venkataramanan s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size, 16139daf8208SAnirudh Venkataramanan GFP_KERNEL); 161480d144c9SAnirudh Venkataramanan if (!s_rule) { 161580d144c9SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 161680d144c9SAnirudh Venkataramanan goto ice_add_mac_exit; 161780d144c9SAnirudh Venkataramanan } 16189daf8208SAnirudh Venkataramanan 16199daf8208SAnirudh Venkataramanan r_iter = s_rule; 16209daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 16219daf8208SAnirudh Venkataramanan struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 162280d144c9SAnirudh Venkataramanan u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 16239daf8208SAnirudh Venkataramanan 162480d144c9SAnirudh Venkataramanan if (is_unicast_ether_addr(mac_addr)) { 162580d144c9SAnirudh Venkataramanan ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 162680d144c9SAnirudh Venkataramanan ice_aqc_opc_add_sw_rules); 16279daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 16289daf8208SAnirudh Venkataramanan ((u8 *)r_iter + s_rule_size); 16299daf8208SAnirudh Venkataramanan } 16309daf8208SAnirudh Venkataramanan } 16319daf8208SAnirudh Venkataramanan 16329daf8208SAnirudh Venkataramanan /* Call AQ bulk switch rule update for all unicast addresses */ 16339daf8208SAnirudh Venkataramanan r_iter = s_rule; 16349daf8208SAnirudh Venkataramanan /* Call AQ switch rule in AQ_MAX chunk */ 16359daf8208SAnirudh Venkataramanan for (total_elem_left = num_unicast; total_elem_left > 0; 16369daf8208SAnirudh Venkataramanan total_elem_left -= elem_sent) { 16379daf8208SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *entry = r_iter; 16389daf8208SAnirudh Venkataramanan 16399daf8208SAnirudh Venkataramanan elem_sent = min(total_elem_left, 16409daf8208SAnirudh Venkataramanan (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size)); 16419daf8208SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 16429daf8208SAnirudh Venkataramanan elem_sent, ice_aqc_opc_add_sw_rules, 16439daf8208SAnirudh Venkataramanan NULL); 16449daf8208SAnirudh Venkataramanan if (status) 16459daf8208SAnirudh Venkataramanan goto ice_add_mac_exit; 16469daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 16479daf8208SAnirudh Venkataramanan ((u8 *)r_iter + (elem_sent * s_rule_size)); 16489daf8208SAnirudh Venkataramanan } 16499daf8208SAnirudh Venkataramanan 16509daf8208SAnirudh Venkataramanan /* Fill up rule id based on the value returned from FW */ 16519daf8208SAnirudh Venkataramanan r_iter = s_rule; 16529daf8208SAnirudh Venkataramanan list_for_each_entry(m_list_itr, m_list, list_entry) { 16539daf8208SAnirudh Venkataramanan struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 165480d144c9SAnirudh Venkataramanan u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 16559daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 16569daf8208SAnirudh Venkataramanan 165780d144c9SAnirudh Venkataramanan if (is_unicast_ether_addr(mac_addr)) { 16589daf8208SAnirudh Venkataramanan f_info->fltr_rule_id = 16599daf8208SAnirudh Venkataramanan le16_to_cpu(r_iter->pdata.lkup_tx_rx.index); 16609daf8208SAnirudh Venkataramanan f_info->fltr_act = ICE_FWD_TO_VSI; 16619daf8208SAnirudh Venkataramanan /* Create an entry to track this MAC address */ 16629daf8208SAnirudh Venkataramanan fm_entry = devm_kzalloc(ice_hw_to_dev(hw), 16639daf8208SAnirudh Venkataramanan sizeof(*fm_entry), GFP_KERNEL); 16649daf8208SAnirudh Venkataramanan if (!fm_entry) { 16659daf8208SAnirudh Venkataramanan status = ICE_ERR_NO_MEMORY; 16669daf8208SAnirudh Venkataramanan goto ice_add_mac_exit; 16679daf8208SAnirudh Venkataramanan } 16689daf8208SAnirudh Venkataramanan fm_entry->fltr_info = *f_info; 16699daf8208SAnirudh Venkataramanan fm_entry->vsi_count = 1; 16709daf8208SAnirudh Venkataramanan /* The book keeping entries will get removed when 16719daf8208SAnirudh Venkataramanan * base driver calls remove filter AQ command 16729daf8208SAnirudh Venkataramanan */ 16739daf8208SAnirudh Venkataramanan 167480d144c9SAnirudh Venkataramanan list_add(&fm_entry->list_entry, rule_head); 16759daf8208SAnirudh Venkataramanan r_iter = (struct ice_aqc_sw_rules_elem *) 16769daf8208SAnirudh Venkataramanan ((u8 *)r_iter + s_rule_size); 16779daf8208SAnirudh Venkataramanan } 16789daf8208SAnirudh Venkataramanan } 16799daf8208SAnirudh Venkataramanan 16809daf8208SAnirudh Venkataramanan ice_add_mac_exit: 168180d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 168280d144c9SAnirudh Venkataramanan if (s_rule) 16839daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 16849daf8208SAnirudh Venkataramanan return status; 16859daf8208SAnirudh Venkataramanan } 16869daf8208SAnirudh Venkataramanan 16879daf8208SAnirudh Venkataramanan /** 1688d76a60baSAnirudh Venkataramanan * ice_add_vlan_internal - Add one VLAN based filter rule 1689d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 1690d76a60baSAnirudh Venkataramanan * @f_entry: filter entry containing one VLAN information 1691d76a60baSAnirudh Venkataramanan */ 1692d76a60baSAnirudh Venkataramanan static enum ice_status 1693d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry) 1694d76a60baSAnirudh Venkataramanan { 169580d144c9SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 1696d76a60baSAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *v_list_itr; 16975726ca0eSAnirudh Venkataramanan struct ice_fltr_info *new_fltr, *cur_fltr; 16985726ca0eSAnirudh Venkataramanan enum ice_sw_lkup_type lkup_type; 16995726ca0eSAnirudh Venkataramanan u16 vsi_list_id = 0, vsi_handle; 170080d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 170180d144c9SAnirudh Venkataramanan enum ice_status status = 0; 1702d76a60baSAnirudh Venkataramanan 17035726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 17045726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 17055726ca0eSAnirudh Venkataramanan 17065726ca0eSAnirudh Venkataramanan f_entry->fltr_info.fwd_id.hw_vsi_id = 17075726ca0eSAnirudh Venkataramanan ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 1708d76a60baSAnirudh Venkataramanan new_fltr = &f_entry->fltr_info; 17095726ca0eSAnirudh Venkataramanan 1710d76a60baSAnirudh Venkataramanan /* VLAN id should only be 12 bits */ 1711d76a60baSAnirudh Venkataramanan if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 1712d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 1713d76a60baSAnirudh Venkataramanan 17145726ca0eSAnirudh Venkataramanan if (new_fltr->src_id != ICE_SRC_ID_VSI) 17155726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 17165726ca0eSAnirudh Venkataramanan 17175726ca0eSAnirudh Venkataramanan new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 17185726ca0eSAnirudh Venkataramanan lkup_type = new_fltr->lkup_type; 17195726ca0eSAnirudh Venkataramanan vsi_handle = new_fltr->vsi_handle; 172080d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 172180d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 172280d144c9SAnirudh Venkataramanan v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr); 1723d76a60baSAnirudh Venkataramanan if (!v_list_itr) { 17245726ca0eSAnirudh Venkataramanan struct ice_vsi_list_map_info *map_info = NULL; 1725d76a60baSAnirudh Venkataramanan 1726d76a60baSAnirudh Venkataramanan if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 17275726ca0eSAnirudh Venkataramanan /* All VLAN pruning rules use a VSI list. Check if 17285726ca0eSAnirudh Venkataramanan * there is already a VSI list containing VSI that we 17295726ca0eSAnirudh Venkataramanan * want to add. If found, use the same vsi_list_id for 17305726ca0eSAnirudh Venkataramanan * this new VLAN rule or else create a new list. 1731d76a60baSAnirudh Venkataramanan */ 17325726ca0eSAnirudh Venkataramanan map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN, 17335726ca0eSAnirudh Venkataramanan vsi_handle, 17345726ca0eSAnirudh Venkataramanan &vsi_list_id); 17355726ca0eSAnirudh Venkataramanan if (!map_info) { 17365726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, 17375726ca0eSAnirudh Venkataramanan &vsi_handle, 17385726ca0eSAnirudh Venkataramanan 1, 1739d76a60baSAnirudh Venkataramanan &vsi_list_id, 1740d76a60baSAnirudh Venkataramanan lkup_type); 1741d76a60baSAnirudh Venkataramanan if (status) 174280d144c9SAnirudh Venkataramanan goto exit; 17435726ca0eSAnirudh Venkataramanan } 17445726ca0eSAnirudh Venkataramanan /* Convert the action to forwarding to a VSI list. */ 1745d76a60baSAnirudh Venkataramanan new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 1746d76a60baSAnirudh Venkataramanan new_fltr->fwd_id.vsi_list_id = vsi_list_id; 1747d76a60baSAnirudh Venkataramanan } 1748d76a60baSAnirudh Venkataramanan 1749d76a60baSAnirudh Venkataramanan status = ice_create_pkt_fwd_rule(hw, f_entry); 17505726ca0eSAnirudh Venkataramanan if (!status) { 175180d144c9SAnirudh Venkataramanan v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, 175280d144c9SAnirudh Venkataramanan new_fltr); 175380d144c9SAnirudh Venkataramanan if (!v_list_itr) { 175480d144c9SAnirudh Venkataramanan status = ICE_ERR_DOES_NOT_EXIST; 175580d144c9SAnirudh Venkataramanan goto exit; 175680d144c9SAnirudh Venkataramanan } 17575726ca0eSAnirudh Venkataramanan /* reuse VSI list for new rule and increment ref_cnt */ 17585726ca0eSAnirudh Venkataramanan if (map_info) { 17595726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info = map_info; 17605726ca0eSAnirudh Venkataramanan map_info->ref_cnt++; 17615726ca0eSAnirudh Venkataramanan } else { 1762d76a60baSAnirudh Venkataramanan v_list_itr->vsi_list_info = 17635726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle, 17645726ca0eSAnirudh Venkataramanan 1, vsi_list_id); 1765d76a60baSAnirudh Venkataramanan } 17665726ca0eSAnirudh Venkataramanan } 17675726ca0eSAnirudh Venkataramanan } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 17685726ca0eSAnirudh Venkataramanan /* Update existing VSI list to add new VSI id only if it used 17695726ca0eSAnirudh Venkataramanan * by one VLAN rule. 17705726ca0eSAnirudh Venkataramanan */ 17715726ca0eSAnirudh Venkataramanan cur_fltr = &v_list_itr->fltr_info; 17725726ca0eSAnirudh Venkataramanan status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 17735726ca0eSAnirudh Venkataramanan new_fltr); 17745726ca0eSAnirudh Venkataramanan } else { 17755726ca0eSAnirudh Venkataramanan /* If VLAN rule exists and VSI list being used by this rule is 17765726ca0eSAnirudh Venkataramanan * referenced by more than 1 VLAN rule. Then create a new VSI 17775726ca0eSAnirudh Venkataramanan * list appending previous VSI with new VSI and update existing 17785726ca0eSAnirudh Venkataramanan * VLAN rule to point to new VSI list id 17795726ca0eSAnirudh Venkataramanan */ 17805726ca0eSAnirudh Venkataramanan struct ice_fltr_info tmp_fltr; 17815726ca0eSAnirudh Venkataramanan u16 vsi_handle_arr[2]; 17825726ca0eSAnirudh Venkataramanan u16 cur_handle; 1783d76a60baSAnirudh Venkataramanan 17845726ca0eSAnirudh Venkataramanan /* Current implementation only supports reusing VSI list with 17855726ca0eSAnirudh Venkataramanan * one VSI count. We should never hit below condition 17865726ca0eSAnirudh Venkataramanan */ 17875726ca0eSAnirudh Venkataramanan if (v_list_itr->vsi_count > 1 && 17885726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info->ref_cnt > 1) { 17895726ca0eSAnirudh Venkataramanan ice_debug(hw, ICE_DBG_SW, 17905726ca0eSAnirudh Venkataramanan "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 17915726ca0eSAnirudh Venkataramanan status = ICE_ERR_CFG; 179280d144c9SAnirudh Venkataramanan goto exit; 1793d76a60baSAnirudh Venkataramanan } 1794d76a60baSAnirudh Venkataramanan 17955726ca0eSAnirudh Venkataramanan cur_handle = 17965726ca0eSAnirudh Venkataramanan find_first_bit(v_list_itr->vsi_list_info->vsi_map, 17975726ca0eSAnirudh Venkataramanan ICE_MAX_VSI); 17985726ca0eSAnirudh Venkataramanan 17995726ca0eSAnirudh Venkataramanan /* A rule already exists with the new VSI being added */ 18005726ca0eSAnirudh Venkataramanan if (cur_handle == vsi_handle) { 18015726ca0eSAnirudh Venkataramanan status = ICE_ERR_ALREADY_EXISTS; 18025726ca0eSAnirudh Venkataramanan goto exit; 18035726ca0eSAnirudh Venkataramanan } 18045726ca0eSAnirudh Venkataramanan 18055726ca0eSAnirudh Venkataramanan vsi_handle_arr[0] = cur_handle; 18065726ca0eSAnirudh Venkataramanan vsi_handle_arr[1] = vsi_handle; 18075726ca0eSAnirudh Venkataramanan status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 18085726ca0eSAnirudh Venkataramanan &vsi_list_id, lkup_type); 18095726ca0eSAnirudh Venkataramanan if (status) 18105726ca0eSAnirudh Venkataramanan goto exit; 18115726ca0eSAnirudh Venkataramanan 18125726ca0eSAnirudh Venkataramanan tmp_fltr = v_list_itr->fltr_info; 18135726ca0eSAnirudh Venkataramanan tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 18145726ca0eSAnirudh Venkataramanan tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 18155726ca0eSAnirudh Venkataramanan tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 18165726ca0eSAnirudh Venkataramanan /* Update the previous switch rule to a new VSI list which 18175726ca0eSAnirudh Venkataramanan * includes current VSI thats requested 18185726ca0eSAnirudh Venkataramanan */ 18195726ca0eSAnirudh Venkataramanan status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 18205726ca0eSAnirudh Venkataramanan if (status) 18215726ca0eSAnirudh Venkataramanan goto exit; 18225726ca0eSAnirudh Venkataramanan 18235726ca0eSAnirudh Venkataramanan /* before overriding VSI list map info. decrement ref_cnt of 18245726ca0eSAnirudh Venkataramanan * previous VSI list 18255726ca0eSAnirudh Venkataramanan */ 18265726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info->ref_cnt--; 18275726ca0eSAnirudh Venkataramanan 18285726ca0eSAnirudh Venkataramanan /* now update to newly created list */ 18295726ca0eSAnirudh Venkataramanan v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 18305726ca0eSAnirudh Venkataramanan v_list_itr->vsi_list_info = 18315726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 18325726ca0eSAnirudh Venkataramanan vsi_list_id); 18335726ca0eSAnirudh Venkataramanan v_list_itr->vsi_count++; 18345726ca0eSAnirudh Venkataramanan } 183580d144c9SAnirudh Venkataramanan 183680d144c9SAnirudh Venkataramanan exit: 183780d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 183880d144c9SAnirudh Venkataramanan return status; 1839d76a60baSAnirudh Venkataramanan } 1840d76a60baSAnirudh Venkataramanan 1841d76a60baSAnirudh Venkataramanan /** 1842d76a60baSAnirudh Venkataramanan * ice_add_vlan - Add VLAN based filter rule 1843d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 1844d76a60baSAnirudh Venkataramanan * @v_list: list of VLAN entries and forwarding information 1845d76a60baSAnirudh Venkataramanan */ 1846d76a60baSAnirudh Venkataramanan enum ice_status 1847d76a60baSAnirudh Venkataramanan ice_add_vlan(struct ice_hw *hw, struct list_head *v_list) 1848d76a60baSAnirudh Venkataramanan { 1849d76a60baSAnirudh Venkataramanan struct ice_fltr_list_entry *v_list_itr; 1850d76a60baSAnirudh Venkataramanan 1851d76a60baSAnirudh Venkataramanan if (!v_list || !hw) 1852d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 1853d76a60baSAnirudh Venkataramanan 1854d76a60baSAnirudh Venkataramanan list_for_each_entry(v_list_itr, v_list, list_entry) { 1855d76a60baSAnirudh Venkataramanan if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 1856d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 185780d144c9SAnirudh Venkataramanan v_list_itr->fltr_info.flag = ICE_FLTR_TX; 185880d144c9SAnirudh Venkataramanan v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr); 185980d144c9SAnirudh Venkataramanan if (v_list_itr->status) 186080d144c9SAnirudh Venkataramanan return v_list_itr->status; 1861d76a60baSAnirudh Venkataramanan } 1862d76a60baSAnirudh Venkataramanan return 0; 1863d76a60baSAnirudh Venkataramanan } 1864d76a60baSAnirudh Venkataramanan 1865d76a60baSAnirudh Venkataramanan /** 18660f9d5027SAnirudh Venkataramanan * ice_rem_sw_rule_info 18670f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 18680f9d5027SAnirudh Venkataramanan * @rule_head: pointer to the switch list structure that we want to delete 18690f9d5027SAnirudh Venkataramanan */ 18700f9d5027SAnirudh Venkataramanan static void 18710f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head) 18720f9d5027SAnirudh Venkataramanan { 18730f9d5027SAnirudh Venkataramanan if (!list_empty(rule_head)) { 18740f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *entry; 18750f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *tmp; 18760f9d5027SAnirudh Venkataramanan 18770f9d5027SAnirudh Venkataramanan list_for_each_entry_safe(entry, tmp, rule_head, list_entry) { 18780f9d5027SAnirudh Venkataramanan list_del(&entry->list_entry); 18790f9d5027SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), entry); 18800f9d5027SAnirudh Venkataramanan } 18810f9d5027SAnirudh Venkataramanan } 18820f9d5027SAnirudh Venkataramanan } 18830f9d5027SAnirudh Venkataramanan 18840f9d5027SAnirudh Venkataramanan /** 188580d144c9SAnirudh Venkataramanan * ice_cfg_dflt_vsi - change state of VSI to set/clear default 1886e94d4478SAnirudh Venkataramanan * @hw: pointer to the hardware structure 18875726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to set as default 1888e94d4478SAnirudh Venkataramanan * @set: true to add the above mentioned switch rule, false to remove it 1889e94d4478SAnirudh Venkataramanan * @direction: ICE_FLTR_RX or ICE_FLTR_TX 189080d144c9SAnirudh Venkataramanan * 189180d144c9SAnirudh Venkataramanan * add filter rule to set/unset given VSI as default VSI for the switch 189280d144c9SAnirudh Venkataramanan * (represented by swid) 1893e94d4478SAnirudh Venkataramanan */ 1894e94d4478SAnirudh Venkataramanan enum ice_status 18955726ca0eSAnirudh Venkataramanan ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction) 1896e94d4478SAnirudh Venkataramanan { 1897e94d4478SAnirudh Venkataramanan struct ice_aqc_sw_rules_elem *s_rule; 1898e94d4478SAnirudh Venkataramanan struct ice_fltr_info f_info; 1899e94d4478SAnirudh Venkataramanan enum ice_adminq_opc opcode; 1900e94d4478SAnirudh Venkataramanan enum ice_status status; 1901e94d4478SAnirudh Venkataramanan u16 s_rule_size; 19025726ca0eSAnirudh Venkataramanan u16 hw_vsi_id; 19035726ca0eSAnirudh Venkataramanan 19045726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 19055726ca0eSAnirudh Venkataramanan return ICE_ERR_PARAM; 19065726ca0eSAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 1907e94d4478SAnirudh Venkataramanan 1908e94d4478SAnirudh Venkataramanan s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE : 1909e94d4478SAnirudh Venkataramanan ICE_SW_RULE_RX_TX_NO_HDR_SIZE; 1910e94d4478SAnirudh Venkataramanan s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 1911e94d4478SAnirudh Venkataramanan if (!s_rule) 1912e94d4478SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 1913e94d4478SAnirudh Venkataramanan 1914e94d4478SAnirudh Venkataramanan memset(&f_info, 0, sizeof(f_info)); 1915e94d4478SAnirudh Venkataramanan 1916e94d4478SAnirudh Venkataramanan f_info.lkup_type = ICE_SW_LKUP_DFLT; 1917e94d4478SAnirudh Venkataramanan f_info.flag = direction; 1918e94d4478SAnirudh Venkataramanan f_info.fltr_act = ICE_FWD_TO_VSI; 19195726ca0eSAnirudh Venkataramanan f_info.fwd_id.hw_vsi_id = hw_vsi_id; 1920e94d4478SAnirudh Venkataramanan 1921e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_RX) { 1922e94d4478SAnirudh Venkataramanan f_info.src = hw->port_info->lport; 19235726ca0eSAnirudh Venkataramanan f_info.src_id = ICE_SRC_ID_LPORT; 1924e94d4478SAnirudh Venkataramanan if (!set) 1925e94d4478SAnirudh Venkataramanan f_info.fltr_rule_id = 1926e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id; 1927e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_TX) { 19285726ca0eSAnirudh Venkataramanan f_info.src_id = ICE_SRC_ID_VSI; 19295726ca0eSAnirudh Venkataramanan f_info.src = hw_vsi_id; 1930e94d4478SAnirudh Venkataramanan if (!set) 1931e94d4478SAnirudh Venkataramanan f_info.fltr_rule_id = 1932e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id; 1933e94d4478SAnirudh Venkataramanan } 1934e94d4478SAnirudh Venkataramanan 1935e94d4478SAnirudh Venkataramanan if (set) 1936e94d4478SAnirudh Venkataramanan opcode = ice_aqc_opc_add_sw_rules; 1937e94d4478SAnirudh Venkataramanan else 1938e94d4478SAnirudh Venkataramanan opcode = ice_aqc_opc_remove_sw_rules; 1939e94d4478SAnirudh Venkataramanan 1940e94d4478SAnirudh Venkataramanan ice_fill_sw_rule(hw, &f_info, s_rule, opcode); 1941e94d4478SAnirudh Venkataramanan 1942e94d4478SAnirudh Venkataramanan status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL); 1943e94d4478SAnirudh Venkataramanan if (status || !(f_info.flag & ICE_FLTR_TX_RX)) 1944e94d4478SAnirudh Venkataramanan goto out; 1945e94d4478SAnirudh Venkataramanan if (set) { 1946e94d4478SAnirudh Venkataramanan u16 index = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index); 1947e94d4478SAnirudh Venkataramanan 1948e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_TX) { 19495726ca0eSAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_num = hw_vsi_id; 1950e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id = index; 1951e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_RX) { 19525726ca0eSAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_num = hw_vsi_id; 1953e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id = index; 1954e94d4478SAnirudh Venkataramanan } 1955e94d4478SAnirudh Venkataramanan } else { 1956e94d4478SAnirudh Venkataramanan if (f_info.flag & ICE_FLTR_TX) { 1957e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 1958e94d4478SAnirudh Venkataramanan hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT; 1959e94d4478SAnirudh Venkataramanan } else if (f_info.flag & ICE_FLTR_RX) { 1960e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 1961e94d4478SAnirudh Venkataramanan hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT; 1962e94d4478SAnirudh Venkataramanan } 1963e94d4478SAnirudh Venkataramanan } 1964e94d4478SAnirudh Venkataramanan 1965e94d4478SAnirudh Venkataramanan out: 1966e94d4478SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), s_rule); 1967e94d4478SAnirudh Venkataramanan return status; 1968e94d4478SAnirudh Venkataramanan } 1969e94d4478SAnirudh Venkataramanan 1970e94d4478SAnirudh Venkataramanan /** 197180d144c9SAnirudh Venkataramanan * ice_remove_mac - remove a MAC address based filter rule 1972d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 197380d144c9SAnirudh Venkataramanan * @m_list: list of MAC addresses and forwarding information 197480d144c9SAnirudh Venkataramanan * 197580d144c9SAnirudh Venkataramanan * This function removes either a MAC filter rule or a specific VSI from a 197680d144c9SAnirudh Venkataramanan * VSI list for a multicast MAC address. 197780d144c9SAnirudh Venkataramanan * 197880d144c9SAnirudh Venkataramanan * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 197980d144c9SAnirudh Venkataramanan * ice_add_mac. Caller should be aware that this call will only work if all 198080d144c9SAnirudh Venkataramanan * the entries passed into m_list were added previously. It will not attempt to 198180d144c9SAnirudh Venkataramanan * do a partial remove of entries that were found. 1982d76a60baSAnirudh Venkataramanan */ 198380d144c9SAnirudh Venkataramanan enum ice_status 198480d144c9SAnirudh Venkataramanan ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) 1985d76a60baSAnirudh Venkataramanan { 198680d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *list_itr; 1987d76a60baSAnirudh Venkataramanan 198880d144c9SAnirudh Venkataramanan if (!m_list) 1989d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 1990d76a60baSAnirudh Venkataramanan 199180d144c9SAnirudh Venkataramanan list_for_each_entry(list_itr, m_list, list_entry) { 199280d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 199380d144c9SAnirudh Venkataramanan 199480d144c9SAnirudh Venkataramanan if (l_type != ICE_SW_LKUP_MAC) 199580d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 199680d144c9SAnirudh Venkataramanan list_itr->status = ice_remove_rule_internal(hw, 199780d144c9SAnirudh Venkataramanan ICE_SW_LKUP_MAC, 199880d144c9SAnirudh Venkataramanan list_itr); 199980d144c9SAnirudh Venkataramanan if (list_itr->status) 200080d144c9SAnirudh Venkataramanan return list_itr->status; 200180d144c9SAnirudh Venkataramanan } 200280d144c9SAnirudh Venkataramanan return 0; 2003d76a60baSAnirudh Venkataramanan } 2004d76a60baSAnirudh Venkataramanan 2005d76a60baSAnirudh Venkataramanan /** 2006d76a60baSAnirudh Venkataramanan * ice_remove_vlan - Remove VLAN based filter rule 2007d76a60baSAnirudh Venkataramanan * @hw: pointer to the hardware structure 2008d76a60baSAnirudh Venkataramanan * @v_list: list of VLAN entries and forwarding information 2009d76a60baSAnirudh Venkataramanan */ 2010d76a60baSAnirudh Venkataramanan enum ice_status 2011d76a60baSAnirudh Venkataramanan ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list) 2012d76a60baSAnirudh Venkataramanan { 2013d76a60baSAnirudh Venkataramanan struct ice_fltr_list_entry *v_list_itr; 2014d76a60baSAnirudh Venkataramanan 2015d76a60baSAnirudh Venkataramanan if (!v_list || !hw) 2016d76a60baSAnirudh Venkataramanan return ICE_ERR_PARAM; 2017d76a60baSAnirudh Venkataramanan 2018d76a60baSAnirudh Venkataramanan list_for_each_entry(v_list_itr, v_list, list_entry) { 201980d144c9SAnirudh Venkataramanan enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 202080d144c9SAnirudh Venkataramanan 202180d144c9SAnirudh Venkataramanan if (l_type != ICE_SW_LKUP_VLAN) 202280d144c9SAnirudh Venkataramanan return ICE_ERR_PARAM; 202380d144c9SAnirudh Venkataramanan v_list_itr->status = ice_remove_rule_internal(hw, 202480d144c9SAnirudh Venkataramanan ICE_SW_LKUP_VLAN, 202580d144c9SAnirudh Venkataramanan v_list_itr); 202680d144c9SAnirudh Venkataramanan if (v_list_itr->status) 202780d144c9SAnirudh Venkataramanan return v_list_itr->status; 2028d76a60baSAnirudh Venkataramanan } 202980d144c9SAnirudh Venkataramanan return 0; 2030d76a60baSAnirudh Venkataramanan } 203180d144c9SAnirudh Venkataramanan 203280d144c9SAnirudh Venkataramanan /** 203380d144c9SAnirudh Venkataramanan * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 203480d144c9SAnirudh Venkataramanan * @fm_entry: filter entry to inspect 20355726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to compare with filter info 203680d144c9SAnirudh Venkataramanan */ 203780d144c9SAnirudh Venkataramanan static bool 20385726ca0eSAnirudh Venkataramanan ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 203980d144c9SAnirudh Venkataramanan { 204080d144c9SAnirudh Venkataramanan return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 20415726ca0eSAnirudh Venkataramanan fm_entry->fltr_info.vsi_handle == vsi_handle) || 204280d144c9SAnirudh Venkataramanan (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 20435726ca0eSAnirudh Venkataramanan (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map)))); 204480d144c9SAnirudh Venkataramanan } 204580d144c9SAnirudh Venkataramanan 204680d144c9SAnirudh Venkataramanan /** 204780d144c9SAnirudh Venkataramanan * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 204880d144c9SAnirudh Venkataramanan * @hw: pointer to the hardware structure 20495726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 205080d144c9SAnirudh Venkataramanan * @vsi_list_head: pointer to the list to add entry to 205180d144c9SAnirudh Venkataramanan * @fi: pointer to fltr_info of filter entry to copy & add 205280d144c9SAnirudh Venkataramanan * 205380d144c9SAnirudh Venkataramanan * Helper function, used when creating a list of filters to remove from 205480d144c9SAnirudh Venkataramanan * a specific VSI. The entry added to vsi_list_head is a COPY of the 205580d144c9SAnirudh Venkataramanan * original filter entry, with the exception of fltr_info.fltr_act and 205680d144c9SAnirudh Venkataramanan * fltr_info.fwd_id fields. These are set such that later logic can 205780d144c9SAnirudh Venkataramanan * extract which VSI to remove the fltr from, and pass on that information. 205880d144c9SAnirudh Venkataramanan */ 205980d144c9SAnirudh Venkataramanan static enum ice_status 20605726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 206180d144c9SAnirudh Venkataramanan struct list_head *vsi_list_head, 206280d144c9SAnirudh Venkataramanan struct ice_fltr_info *fi) 206380d144c9SAnirudh Venkataramanan { 206480d144c9SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 206580d144c9SAnirudh Venkataramanan 206680d144c9SAnirudh Venkataramanan /* this memory is freed up in the caller function 206780d144c9SAnirudh Venkataramanan * once filters for this VSI are removed 206880d144c9SAnirudh Venkataramanan */ 206980d144c9SAnirudh Venkataramanan tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL); 207080d144c9SAnirudh Venkataramanan if (!tmp) 207180d144c9SAnirudh Venkataramanan return ICE_ERR_NO_MEMORY; 207280d144c9SAnirudh Venkataramanan 207380d144c9SAnirudh Venkataramanan tmp->fltr_info = *fi; 207480d144c9SAnirudh Venkataramanan 207580d144c9SAnirudh Venkataramanan /* Overwrite these fields to indicate which VSI to remove filter from, 207680d144c9SAnirudh Venkataramanan * so find and remove logic can extract the information from the 207780d144c9SAnirudh Venkataramanan * list entries. Note that original entries will still have proper 207880d144c9SAnirudh Venkataramanan * values. 207980d144c9SAnirudh Venkataramanan */ 208080d144c9SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 20815726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi_handle; 20825726ca0eSAnirudh Venkataramanan tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 208380d144c9SAnirudh Venkataramanan 208480d144c9SAnirudh Venkataramanan list_add(&tmp->list_entry, vsi_list_head); 208580d144c9SAnirudh Venkataramanan 208680d144c9SAnirudh Venkataramanan return 0; 2087d76a60baSAnirudh Venkataramanan } 2088d76a60baSAnirudh Venkataramanan 2089d76a60baSAnirudh Venkataramanan /** 20909daf8208SAnirudh Venkataramanan * ice_add_to_vsi_fltr_list - Add VSI filters to the list 20919daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 20925726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 20939daf8208SAnirudh Venkataramanan * @lkup_list_head: pointer to the list that has certain lookup type filters 20945726ca0eSAnirudh Venkataramanan * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 209580d144c9SAnirudh Venkataramanan * 209680d144c9SAnirudh Venkataramanan * Locates all filters in lkup_list_head that are used by the given VSI, 209780d144c9SAnirudh Venkataramanan * and adds COPIES of those entries to vsi_list_head (intended to be used 209880d144c9SAnirudh Venkataramanan * to remove the listed filters). 209980d144c9SAnirudh Venkataramanan * Note that this means all entries in vsi_list_head must be explicitly 210080d144c9SAnirudh Venkataramanan * deallocated by the caller when done with list. 21019daf8208SAnirudh Venkataramanan */ 21029daf8208SAnirudh Venkataramanan static enum ice_status 21035726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 21049daf8208SAnirudh Venkataramanan struct list_head *lkup_list_head, 21059daf8208SAnirudh Venkataramanan struct list_head *vsi_list_head) 21069daf8208SAnirudh Venkataramanan { 21079daf8208SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *fm_entry; 210880d144c9SAnirudh Venkataramanan enum ice_status status = 0; 21099daf8208SAnirudh Venkataramanan 21109daf8208SAnirudh Venkataramanan /* check to make sure VSI id is valid and within boundary */ 21115726ca0eSAnirudh Venkataramanan if (!ice_is_vsi_valid(hw, vsi_handle)) 21129daf8208SAnirudh Venkataramanan return ICE_ERR_PARAM; 21139daf8208SAnirudh Venkataramanan 21149daf8208SAnirudh Venkataramanan list_for_each_entry(fm_entry, lkup_list_head, list_entry) { 21159daf8208SAnirudh Venkataramanan struct ice_fltr_info *fi; 21169daf8208SAnirudh Venkataramanan 21179daf8208SAnirudh Venkataramanan fi = &fm_entry->fltr_info; 21185726ca0eSAnirudh Venkataramanan if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) 211980d144c9SAnirudh Venkataramanan continue; 21209daf8208SAnirudh Venkataramanan 21215726ca0eSAnirudh Venkataramanan status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 212280d144c9SAnirudh Venkataramanan vsi_list_head, fi); 212380d144c9SAnirudh Venkataramanan if (status) 212480d144c9SAnirudh Venkataramanan return status; 21259daf8208SAnirudh Venkataramanan } 212680d144c9SAnirudh Venkataramanan return status; 21279daf8208SAnirudh Venkataramanan } 21289daf8208SAnirudh Venkataramanan 21299daf8208SAnirudh Venkataramanan /** 21309daf8208SAnirudh Venkataramanan * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 21319daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 21325726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 21339daf8208SAnirudh Venkataramanan * @lkup: switch rule filter lookup type 21349daf8208SAnirudh Venkataramanan */ 21359daf8208SAnirudh Venkataramanan static void 21365726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 21379daf8208SAnirudh Venkataramanan enum ice_sw_lkup_type lkup) 21389daf8208SAnirudh Venkataramanan { 21399daf8208SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 21409daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *fm_entry; 21419daf8208SAnirudh Venkataramanan struct list_head remove_list_head; 214280d144c9SAnirudh Venkataramanan struct list_head *rule_head; 21439daf8208SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 214480d144c9SAnirudh Venkataramanan struct mutex *rule_lock; /* Lock to protect filter rule list */ 21459daf8208SAnirudh Venkataramanan enum ice_status status; 21469daf8208SAnirudh Venkataramanan 21479daf8208SAnirudh Venkataramanan INIT_LIST_HEAD(&remove_list_head); 214880d144c9SAnirudh Venkataramanan rule_lock = &sw->recp_list[lkup].filt_rule_lock; 214980d144c9SAnirudh Venkataramanan rule_head = &sw->recp_list[lkup].filt_rules; 215080d144c9SAnirudh Venkataramanan mutex_lock(rule_lock); 21515726ca0eSAnirudh Venkataramanan status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 215280d144c9SAnirudh Venkataramanan &remove_list_head); 215380d144c9SAnirudh Venkataramanan mutex_unlock(rule_lock); 215480d144c9SAnirudh Venkataramanan if (status) 215580d144c9SAnirudh Venkataramanan return; 215680d144c9SAnirudh Venkataramanan 21579daf8208SAnirudh Venkataramanan switch (lkup) { 21589daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC: 21599daf8208SAnirudh Venkataramanan ice_remove_mac(hw, &remove_list_head); 21609daf8208SAnirudh Venkataramanan break; 21619daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_VLAN: 2162d76a60baSAnirudh Venkataramanan ice_remove_vlan(hw, &remove_list_head); 2163d76a60baSAnirudh Venkataramanan break; 21649daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_MAC_VLAN: 21659daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE: 21669daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_ETHERTYPE_MAC: 21679daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC: 21689daf8208SAnirudh Venkataramanan case ICE_SW_LKUP_DFLT: 216980d144c9SAnirudh Venkataramanan case ICE_SW_LKUP_PROMISC_VLAN: 217080d144c9SAnirudh Venkataramanan case ICE_SW_LKUP_LAST: 217180d144c9SAnirudh Venkataramanan default: 217280d144c9SAnirudh Venkataramanan ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup); 21739daf8208SAnirudh Venkataramanan break; 21749daf8208SAnirudh Venkataramanan } 21759daf8208SAnirudh Venkataramanan 21769daf8208SAnirudh Venkataramanan list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { 21779daf8208SAnirudh Venkataramanan list_del(&fm_entry->list_entry); 21789daf8208SAnirudh Venkataramanan devm_kfree(ice_hw_to_dev(hw), fm_entry); 21799daf8208SAnirudh Venkataramanan } 21809daf8208SAnirudh Venkataramanan } 21819daf8208SAnirudh Venkataramanan 21829daf8208SAnirudh Venkataramanan /** 21839daf8208SAnirudh Venkataramanan * ice_remove_vsi_fltr - Remove all filters for a VSI 21849daf8208SAnirudh Venkataramanan * @hw: pointer to the hardware structure 21855726ca0eSAnirudh Venkataramanan * @vsi_handle: VSI handle to remove filters from 21869daf8208SAnirudh Venkataramanan */ 21875726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 21889daf8208SAnirudh Venkataramanan { 21895726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC); 21905726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN); 21915726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC); 21925726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN); 21935726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT); 21945726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE); 21955726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC); 21965726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN); 21979daf8208SAnirudh Venkataramanan } 21980f9d5027SAnirudh Venkataramanan 21990f9d5027SAnirudh Venkataramanan /** 2200334cb062SAnirudh Venkataramanan * ice_replay_vsi_fltr - Replay filters for requested VSI 22010f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 2202334cb062SAnirudh Venkataramanan * @vsi_handle: driver VSI handle 22030f9d5027SAnirudh Venkataramanan * @recp_id: Recipe id for which rules need to be replayed 2204334cb062SAnirudh Venkataramanan * @list_head: list for which filters need to be replayed 2205334cb062SAnirudh Venkataramanan * 2206334cb062SAnirudh Venkataramanan * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 2207334cb062SAnirudh Venkataramanan * It is required to pass valid VSI handle. 22080f9d5027SAnirudh Venkataramanan */ 22090f9d5027SAnirudh Venkataramanan static enum ice_status 2210334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id, 2211334cb062SAnirudh Venkataramanan struct list_head *list_head) 22120f9d5027SAnirudh Venkataramanan { 22130f9d5027SAnirudh Venkataramanan struct ice_fltr_mgmt_list_entry *itr; 22140f9d5027SAnirudh Venkataramanan enum ice_status status = 0; 2215334cb062SAnirudh Venkataramanan u16 hw_vsi_id; 22160f9d5027SAnirudh Venkataramanan 22170f9d5027SAnirudh Venkataramanan if (list_empty(list_head)) 22180f9d5027SAnirudh Venkataramanan return status; 2219334cb062SAnirudh Venkataramanan hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 22200f9d5027SAnirudh Venkataramanan 2221334cb062SAnirudh Venkataramanan list_for_each_entry(itr, list_head, list_entry) { 22220f9d5027SAnirudh Venkataramanan struct ice_fltr_list_entry f_entry; 22230f9d5027SAnirudh Venkataramanan 22240f9d5027SAnirudh Venkataramanan f_entry.fltr_info = itr->fltr_info; 2225334cb062SAnirudh Venkataramanan if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 2226334cb062SAnirudh Venkataramanan itr->fltr_info.vsi_handle == vsi_handle) { 2227334cb062SAnirudh Venkataramanan /* update the src in case it is vsi num */ 2228334cb062SAnirudh Venkataramanan if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 2229334cb062SAnirudh Venkataramanan f_entry.fltr_info.src = hw_vsi_id; 22300f9d5027SAnirudh Venkataramanan status = ice_add_rule_internal(hw, recp_id, &f_entry); 22310f9d5027SAnirudh Venkataramanan if (status) 22320f9d5027SAnirudh Venkataramanan goto end; 22330f9d5027SAnirudh Venkataramanan continue; 22340f9d5027SAnirudh Venkataramanan } 2235334cb062SAnirudh Venkataramanan if (!test_bit(vsi_handle, itr->vsi_list_info->vsi_map)) 2236334cb062SAnirudh Venkataramanan continue; 2237334cb062SAnirudh Venkataramanan /* Clearing it so that the logic can add it back */ 2238334cb062SAnirudh Venkataramanan clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 2239334cb062SAnirudh Venkataramanan f_entry.fltr_info.vsi_handle = vsi_handle; 22400f9d5027SAnirudh Venkataramanan f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 2241334cb062SAnirudh Venkataramanan /* update the src in case it is vsi num */ 2242334cb062SAnirudh Venkataramanan if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 2243334cb062SAnirudh Venkataramanan f_entry.fltr_info.src = hw_vsi_id; 22440f9d5027SAnirudh Venkataramanan if (recp_id == ICE_SW_LKUP_VLAN) 22450f9d5027SAnirudh Venkataramanan status = ice_add_vlan_internal(hw, &f_entry); 22460f9d5027SAnirudh Venkataramanan else 2247334cb062SAnirudh Venkataramanan status = ice_add_rule_internal(hw, recp_id, &f_entry); 22480f9d5027SAnirudh Venkataramanan if (status) 22490f9d5027SAnirudh Venkataramanan goto end; 22500f9d5027SAnirudh Venkataramanan } 22510f9d5027SAnirudh Venkataramanan end: 22520f9d5027SAnirudh Venkataramanan return status; 22530f9d5027SAnirudh Venkataramanan } 22540f9d5027SAnirudh Venkataramanan 22550f9d5027SAnirudh Venkataramanan /** 2256334cb062SAnirudh Venkataramanan * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 22570f9d5027SAnirudh Venkataramanan * @hw: pointer to the hardware structure 2258334cb062SAnirudh Venkataramanan * @vsi_handle: driver VSI handle 22590f9d5027SAnirudh Venkataramanan * 2260334cb062SAnirudh Venkataramanan * Replays filters for requested VSI via vsi_handle. 22610f9d5027SAnirudh Venkataramanan */ 2262334cb062SAnirudh Venkataramanan enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle) 22630f9d5027SAnirudh Venkataramanan { 22640f9d5027SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 22650f9d5027SAnirudh Venkataramanan enum ice_status status = 0; 22660f9d5027SAnirudh Venkataramanan u8 i; 22670f9d5027SAnirudh Venkataramanan 22680f9d5027SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 2269334cb062SAnirudh Venkataramanan struct list_head *head; 22700f9d5027SAnirudh Venkataramanan 2271334cb062SAnirudh Venkataramanan head = &sw->recp_list[i].filt_replay_rules; 2272334cb062SAnirudh Venkataramanan status = ice_replay_vsi_fltr(hw, vsi_handle, i, head); 22730f9d5027SAnirudh Venkataramanan if (status) 22740f9d5027SAnirudh Venkataramanan return status; 22750f9d5027SAnirudh Venkataramanan } 22760f9d5027SAnirudh Venkataramanan return status; 22770f9d5027SAnirudh Venkataramanan } 2278334cb062SAnirudh Venkataramanan 2279334cb062SAnirudh Venkataramanan /** 2280334cb062SAnirudh Venkataramanan * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 2281334cb062SAnirudh Venkataramanan * @hw: pointer to the hw struct 2282334cb062SAnirudh Venkataramanan * 2283334cb062SAnirudh Venkataramanan * Deletes the filter replay rules. 2284334cb062SAnirudh Venkataramanan */ 2285334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 2286334cb062SAnirudh Venkataramanan { 2287334cb062SAnirudh Venkataramanan struct ice_switch_info *sw = hw->switch_info; 2288334cb062SAnirudh Venkataramanan u8 i; 2289334cb062SAnirudh Venkataramanan 2290334cb062SAnirudh Venkataramanan if (!sw) 2291334cb062SAnirudh Venkataramanan return; 2292334cb062SAnirudh Venkataramanan 2293334cb062SAnirudh Venkataramanan for (i = 0; i < ICE_SW_LKUP_LAST; i++) { 2294334cb062SAnirudh Venkataramanan if (!list_empty(&sw->recp_list[i].filt_replay_rules)) { 2295334cb062SAnirudh Venkataramanan struct list_head *l_head; 2296334cb062SAnirudh Venkataramanan 2297334cb062SAnirudh Venkataramanan l_head = &sw->recp_list[i].filt_replay_rules; 2298334cb062SAnirudh Venkataramanan ice_rem_sw_rule_info(hw, l_head); 2299334cb062SAnirudh Venkataramanan } 2300334cb062SAnirudh Venkataramanan } 2301334cb062SAnirudh Venkataramanan } 2302