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