11b8f15b6SMichal Swiatkowski // SPDX-License-Identifier: GPL-2.0
21b8f15b6SMichal Swiatkowski /* Copyright (C) 2018-2020, Intel Corporation. */
31b8f15b6SMichal Swiatkowski 
41b8f15b6SMichal Swiatkowski #include "ice.h"
51b8f15b6SMichal Swiatkowski #include "ice_fltr.h"
61b8f15b6SMichal Swiatkowski 
71b8f15b6SMichal Swiatkowski /**
81b8f15b6SMichal Swiatkowski  * ice_fltr_free_list - free filter lists helper
91b8f15b6SMichal Swiatkowski  * @dev: pointer to the device struct
101b8f15b6SMichal Swiatkowski  * @h: pointer to the list head to be freed
111b8f15b6SMichal Swiatkowski  *
121b8f15b6SMichal Swiatkowski  * Helper function to free filter lists previously created using
131b8f15b6SMichal Swiatkowski  * ice_fltr_add_mac_to_list
141b8f15b6SMichal Swiatkowski  */
151b8f15b6SMichal Swiatkowski void ice_fltr_free_list(struct device *dev, struct list_head *h)
161b8f15b6SMichal Swiatkowski {
171b8f15b6SMichal Swiatkowski 	struct ice_fltr_list_entry *e, *tmp;
181b8f15b6SMichal Swiatkowski 
191b8f15b6SMichal Swiatkowski 	list_for_each_entry_safe(e, tmp, h, list_entry) {
201b8f15b6SMichal Swiatkowski 		list_del(&e->list_entry);
211b8f15b6SMichal Swiatkowski 		devm_kfree(dev, e);
221b8f15b6SMichal Swiatkowski 	}
231b8f15b6SMichal Swiatkowski }
241b8f15b6SMichal Swiatkowski 
251b8f15b6SMichal Swiatkowski /**
261b8f15b6SMichal Swiatkowski  * ice_fltr_add_entry_to_list - allocate and add filter entry to list
271b8f15b6SMichal Swiatkowski  * @dev: pointer to device needed by alloc function
281b8f15b6SMichal Swiatkowski  * @info: filter info struct that gets added to the passed in list
291b8f15b6SMichal Swiatkowski  * @list: pointer to the list which contains MAC filters entry
301b8f15b6SMichal Swiatkowski  */
311b8f15b6SMichal Swiatkowski static int
321b8f15b6SMichal Swiatkowski ice_fltr_add_entry_to_list(struct device *dev, struct ice_fltr_info *info,
331b8f15b6SMichal Swiatkowski 			   struct list_head *list)
341b8f15b6SMichal Swiatkowski {
351b8f15b6SMichal Swiatkowski 	struct ice_fltr_list_entry *entry;
361b8f15b6SMichal Swiatkowski 
371b8f15b6SMichal Swiatkowski 	entry = devm_kzalloc(dev, sizeof(*entry), GFP_ATOMIC);
381b8f15b6SMichal Swiatkowski 	if (!entry)
391b8f15b6SMichal Swiatkowski 		return -ENOMEM;
401b8f15b6SMichal Swiatkowski 
411b8f15b6SMichal Swiatkowski 	entry->fltr_info = *info;
421b8f15b6SMichal Swiatkowski 
431b8f15b6SMichal Swiatkowski 	INIT_LIST_HEAD(&entry->list_entry);
441b8f15b6SMichal Swiatkowski 	list_add(&entry->list_entry, list);
451b8f15b6SMichal Swiatkowski 
461b8f15b6SMichal Swiatkowski 	return 0;
471b8f15b6SMichal Swiatkowski }
481b8f15b6SMichal Swiatkowski 
491b8f15b6SMichal Swiatkowski /**
50fabf480bSBrett Creeley  * ice_fltr_set_vlan_vsi_promisc
51fabf480bSBrett Creeley  * @hw: pointer to the hardware structure
52fabf480bSBrett Creeley  * @vsi: the VSI being configured
53fabf480bSBrett Creeley  * @promisc_mask: mask of promiscuous config bits
54fabf480bSBrett Creeley  *
55fabf480bSBrett Creeley  * Set VSI with all associated VLANs to given promiscuous mode(s)
56fabf480bSBrett Creeley  */
575e24d598STony Nguyen int
58fabf480bSBrett Creeley ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
59fabf480bSBrett Creeley 			      u8 promisc_mask)
60fabf480bSBrett Creeley {
61fabf480bSBrett Creeley 	return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false);
62fabf480bSBrett Creeley }
63fabf480bSBrett Creeley 
64fabf480bSBrett Creeley /**
65fabf480bSBrett Creeley  * ice_fltr_clear_vlan_vsi_promisc
66fabf480bSBrett Creeley  * @hw: pointer to the hardware structure
67fabf480bSBrett Creeley  * @vsi: the VSI being configured
68fabf480bSBrett Creeley  * @promisc_mask: mask of promiscuous config bits
69fabf480bSBrett Creeley  *
70fabf480bSBrett Creeley  * Clear VSI with all associated VLANs to given promiscuous mode(s)
71fabf480bSBrett Creeley  */
725e24d598STony Nguyen int
73fabf480bSBrett Creeley ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
74fabf480bSBrett Creeley 				u8 promisc_mask)
75fabf480bSBrett Creeley {
76fabf480bSBrett Creeley 	return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true);
77fabf480bSBrett Creeley }
78fabf480bSBrett Creeley 
79fabf480bSBrett Creeley /**
80fabf480bSBrett Creeley  * ice_fltr_clear_vsi_promisc - clear specified promiscuous mode(s)
81fabf480bSBrett Creeley  * @hw: pointer to the hardware structure
82fabf480bSBrett Creeley  * @vsi_handle: VSI handle to clear mode
83fabf480bSBrett Creeley  * @promisc_mask: mask of promiscuous config bits to clear
84fabf480bSBrett Creeley  * @vid: VLAN ID to clear VLAN promiscuous
85fabf480bSBrett Creeley  */
865e24d598STony Nguyen int
87fabf480bSBrett Creeley ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
88fabf480bSBrett Creeley 			   u16 vid)
89fabf480bSBrett Creeley {
90fabf480bSBrett Creeley 	return ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
91fabf480bSBrett Creeley }
92fabf480bSBrett Creeley 
93fabf480bSBrett Creeley /**
94fabf480bSBrett Creeley  * ice_fltr_set_vsi_promisc - set given VSI to given promiscuous mode(s)
95fabf480bSBrett Creeley  * @hw: pointer to the hardware structure
96fabf480bSBrett Creeley  * @vsi_handle: VSI handle to configure
97fabf480bSBrett Creeley  * @promisc_mask: mask of promiscuous config bits
98fabf480bSBrett Creeley  * @vid: VLAN ID to set VLAN promiscuous
99fabf480bSBrett Creeley  */
1005e24d598STony Nguyen int
101fabf480bSBrett Creeley ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
102fabf480bSBrett Creeley 			 u16 vid)
103fabf480bSBrett Creeley {
104fabf480bSBrett Creeley 	return ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
105fabf480bSBrett Creeley }
106fabf480bSBrett Creeley 
107fabf480bSBrett Creeley /**
1081b8f15b6SMichal Swiatkowski  * ice_fltr_add_mac_list - add list of MAC filters
1091b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1101b8f15b6SMichal Swiatkowski  * @list: list of filters
1111b8f15b6SMichal Swiatkowski  */
1125e24d598STony Nguyen int
1131b8f15b6SMichal Swiatkowski ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list)
1141b8f15b6SMichal Swiatkowski {
1151b8f15b6SMichal Swiatkowski 	return ice_add_mac(&vsi->back->hw, list);
1161b8f15b6SMichal Swiatkowski }
1171b8f15b6SMichal Swiatkowski 
1181b8f15b6SMichal Swiatkowski /**
1191b8f15b6SMichal Swiatkowski  * ice_fltr_remove_mac_list - remove list of MAC filters
1201b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1211b8f15b6SMichal Swiatkowski  * @list: list of filters
1221b8f15b6SMichal Swiatkowski  */
1235e24d598STony Nguyen int
1241b8f15b6SMichal Swiatkowski ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list)
1251b8f15b6SMichal Swiatkowski {
1261b8f15b6SMichal Swiatkowski 	return ice_remove_mac(&vsi->back->hw, list);
1271b8f15b6SMichal Swiatkowski }
1281b8f15b6SMichal Swiatkowski 
1291b8f15b6SMichal Swiatkowski /**
1301b8f15b6SMichal Swiatkowski  * ice_fltr_add_vlan_list - add list of VLAN filters
1311b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1321b8f15b6SMichal Swiatkowski  * @list: list of filters
1331b8f15b6SMichal Swiatkowski  */
1345e24d598STony Nguyen static int
1351b8f15b6SMichal Swiatkowski ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list)
1361b8f15b6SMichal Swiatkowski {
1371b8f15b6SMichal Swiatkowski 	return ice_add_vlan(&vsi->back->hw, list);
1381b8f15b6SMichal Swiatkowski }
1391b8f15b6SMichal Swiatkowski 
1401b8f15b6SMichal Swiatkowski /**
1411b8f15b6SMichal Swiatkowski  * ice_fltr_remove_vlan_list - remove list of VLAN filters
1421b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1431b8f15b6SMichal Swiatkowski  * @list: list of filters
1441b8f15b6SMichal Swiatkowski  */
1455e24d598STony Nguyen static int
1461b8f15b6SMichal Swiatkowski ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list)
1471b8f15b6SMichal Swiatkowski {
1481b8f15b6SMichal Swiatkowski 	return ice_remove_vlan(&vsi->back->hw, list);
1491b8f15b6SMichal Swiatkowski }
1501b8f15b6SMichal Swiatkowski 
1511b8f15b6SMichal Swiatkowski /**
1521b8f15b6SMichal Swiatkowski  * ice_fltr_add_eth_list - add list of ethertype filters
1531b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1541b8f15b6SMichal Swiatkowski  * @list: list of filters
1551b8f15b6SMichal Swiatkowski  */
1565e24d598STony Nguyen static int
1571b8f15b6SMichal Swiatkowski ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list)
1581b8f15b6SMichal Swiatkowski {
1591b8f15b6SMichal Swiatkowski 	return ice_add_eth_mac(&vsi->back->hw, list);
1601b8f15b6SMichal Swiatkowski }
1611b8f15b6SMichal Swiatkowski 
1621b8f15b6SMichal Swiatkowski /**
1631b8f15b6SMichal Swiatkowski  * ice_fltr_remove_eth_list - remove list of ethertype filters
1641b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1651b8f15b6SMichal Swiatkowski  * @list: list of filters
1661b8f15b6SMichal Swiatkowski  */
1675e24d598STony Nguyen static int
1681b8f15b6SMichal Swiatkowski ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list)
1691b8f15b6SMichal Swiatkowski {
1701b8f15b6SMichal Swiatkowski 	return ice_remove_eth_mac(&vsi->back->hw, list);
1711b8f15b6SMichal Swiatkowski }
1721b8f15b6SMichal Swiatkowski 
1731b8f15b6SMichal Swiatkowski /**
1741b8f15b6SMichal Swiatkowski  * ice_fltr_remove_all - remove all filters associated with VSI
1751b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1761b8f15b6SMichal Swiatkowski  */
1771b8f15b6SMichal Swiatkowski void ice_fltr_remove_all(struct ice_vsi *vsi)
1781b8f15b6SMichal Swiatkowski {
1791b8f15b6SMichal Swiatkowski 	ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);
1801b8f15b6SMichal Swiatkowski }
1811b8f15b6SMichal Swiatkowski 
1821b8f15b6SMichal Swiatkowski /**
1831b8f15b6SMichal Swiatkowski  * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list
1841b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
1851b8f15b6SMichal Swiatkowski  * @list: list to add filter info to
1861b8f15b6SMichal Swiatkowski  * @mac: MAC address to add
1871b8f15b6SMichal Swiatkowski  * @action: filter action
1881b8f15b6SMichal Swiatkowski  */
1891b8f15b6SMichal Swiatkowski int
1901b8f15b6SMichal Swiatkowski ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list,
1911b8f15b6SMichal Swiatkowski 			 const u8 *mac, enum ice_sw_fwd_act_type action)
1921b8f15b6SMichal Swiatkowski {
1931b8f15b6SMichal Swiatkowski 	struct ice_fltr_info info = { 0 };
1941b8f15b6SMichal Swiatkowski 
1951b8f15b6SMichal Swiatkowski 	info.flag = ICE_FLTR_TX;
1961b8f15b6SMichal Swiatkowski 	info.src_id = ICE_SRC_ID_VSI;
1971b8f15b6SMichal Swiatkowski 	info.lkup_type = ICE_SW_LKUP_MAC;
1981b8f15b6SMichal Swiatkowski 	info.fltr_act = action;
1991b8f15b6SMichal Swiatkowski 	info.vsi_handle = vsi->idx;
2001b8f15b6SMichal Swiatkowski 
2011b8f15b6SMichal Swiatkowski 	ether_addr_copy(info.l_data.mac.mac_addr, mac);
2021b8f15b6SMichal Swiatkowski 
2031b8f15b6SMichal Swiatkowski 	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
2041b8f15b6SMichal Swiatkowski 					  list);
2051b8f15b6SMichal Swiatkowski }
2061b8f15b6SMichal Swiatkowski 
2071b8f15b6SMichal Swiatkowski /**
2081b8f15b6SMichal Swiatkowski  * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list
2091b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
2101b8f15b6SMichal Swiatkowski  * @list: list to add filter info to
2111b8f15b6SMichal Swiatkowski  * @vlan_id: VLAN ID to add
2121b8f15b6SMichal Swiatkowski  * @action: filter action
2131b8f15b6SMichal Swiatkowski  */
2141b8f15b6SMichal Swiatkowski static int
2151b8f15b6SMichal Swiatkowski ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list,
2161b8f15b6SMichal Swiatkowski 			  u16 vlan_id, enum ice_sw_fwd_act_type action)
2171b8f15b6SMichal Swiatkowski {
2181b8f15b6SMichal Swiatkowski 	struct ice_fltr_info info = { 0 };
2191b8f15b6SMichal Swiatkowski 
2201b8f15b6SMichal Swiatkowski 	info.flag = ICE_FLTR_TX;
2211b8f15b6SMichal Swiatkowski 	info.src_id = ICE_SRC_ID_VSI;
2221b8f15b6SMichal Swiatkowski 	info.lkup_type = ICE_SW_LKUP_VLAN;
2231b8f15b6SMichal Swiatkowski 	info.fltr_act = action;
2241b8f15b6SMichal Swiatkowski 	info.vsi_handle = vsi->idx;
2251b8f15b6SMichal Swiatkowski 	info.l_data.vlan.vlan_id = vlan_id;
2261b8f15b6SMichal Swiatkowski 
2271b8f15b6SMichal Swiatkowski 	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
2281b8f15b6SMichal Swiatkowski 					  list);
2291b8f15b6SMichal Swiatkowski }
2301b8f15b6SMichal Swiatkowski 
2311b8f15b6SMichal Swiatkowski /**
2321b8f15b6SMichal Swiatkowski  * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list
2331b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
2341b8f15b6SMichal Swiatkowski  * @list: list to add filter info to
2351b8f15b6SMichal Swiatkowski  * @ethertype: ethertype of packet that matches filter
2361b8f15b6SMichal Swiatkowski  * @flag: filter direction, Tx or Rx
2371b8f15b6SMichal Swiatkowski  * @action: filter action
2381b8f15b6SMichal Swiatkowski  */
2391b8f15b6SMichal Swiatkowski static int
2401b8f15b6SMichal Swiatkowski ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list,
2411b8f15b6SMichal Swiatkowski 			 u16 ethertype, u16 flag,
2421b8f15b6SMichal Swiatkowski 			 enum ice_sw_fwd_act_type action)
2431b8f15b6SMichal Swiatkowski {
2441b8f15b6SMichal Swiatkowski 	struct ice_fltr_info info = { 0 };
2451b8f15b6SMichal Swiatkowski 
2461b8f15b6SMichal Swiatkowski 	info.flag = flag;
2471b8f15b6SMichal Swiatkowski 	info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
2481b8f15b6SMichal Swiatkowski 	info.fltr_act = action;
2491b8f15b6SMichal Swiatkowski 	info.vsi_handle = vsi->idx;
2501b8f15b6SMichal Swiatkowski 	info.l_data.ethertype_mac.ethertype = ethertype;
2511b8f15b6SMichal Swiatkowski 
2521b8f15b6SMichal Swiatkowski 	if (flag == ICE_FLTR_TX)
2531b8f15b6SMichal Swiatkowski 		info.src_id = ICE_SRC_ID_VSI;
2541b8f15b6SMichal Swiatkowski 	else
2551b8f15b6SMichal Swiatkowski 		info.src_id = ICE_SRC_ID_LPORT;
2561b8f15b6SMichal Swiatkowski 
2571b8f15b6SMichal Swiatkowski 	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
2581b8f15b6SMichal Swiatkowski 					  list);
2591b8f15b6SMichal Swiatkowski }
2601b8f15b6SMichal Swiatkowski 
2611b8f15b6SMichal Swiatkowski /**
2621b8f15b6SMichal Swiatkowski  * ice_fltr_prepare_mac - add or remove MAC rule
2631b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
2641b8f15b6SMichal Swiatkowski  * @mac: MAC address to add
2651b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
2661b8f15b6SMichal Swiatkowski  * @mac_action: pointer to add or remove MAC function
2671b8f15b6SMichal Swiatkowski  */
2685e24d598STony Nguyen static int
2691b8f15b6SMichal Swiatkowski ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac,
2701b8f15b6SMichal Swiatkowski 		     enum ice_sw_fwd_act_type action,
2715e24d598STony Nguyen 		     int (*mac_action)(struct ice_vsi *, struct list_head *))
2721b8f15b6SMichal Swiatkowski {
2735e24d598STony Nguyen 	int result;
2741b8f15b6SMichal Swiatkowski 	LIST_HEAD(tmp_list);
2751b8f15b6SMichal Swiatkowski 
2761b8f15b6SMichal Swiatkowski 	if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) {
2771b8f15b6SMichal Swiatkowski 		ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
278*d54699e2STony Nguyen 		return -ENOMEM;
2791b8f15b6SMichal Swiatkowski 	}
2801b8f15b6SMichal Swiatkowski 
2811b8f15b6SMichal Swiatkowski 	result = mac_action(vsi, &tmp_list);
2821b8f15b6SMichal Swiatkowski 	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
2831b8f15b6SMichal Swiatkowski 	return result;
2841b8f15b6SMichal Swiatkowski }
2851b8f15b6SMichal Swiatkowski 
2861b8f15b6SMichal Swiatkowski /**
2871b8f15b6SMichal Swiatkowski  * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter
2881b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
2891b8f15b6SMichal Swiatkowski  * @mac: MAC address to add
2901b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
2911b8f15b6SMichal Swiatkowski  * @mac_action: pointer to add or remove MAC function
2921b8f15b6SMichal Swiatkowski  */
2935e24d598STony Nguyen static int
2941b8f15b6SMichal Swiatkowski ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
2951b8f15b6SMichal Swiatkowski 				   enum ice_sw_fwd_act_type action,
2965e24d598STony Nguyen 				   int(*mac_action)
2971b8f15b6SMichal Swiatkowski 				   (struct ice_vsi *, struct list_head *))
2981b8f15b6SMichal Swiatkowski {
2991b8f15b6SMichal Swiatkowski 	u8 broadcast[ETH_ALEN];
3005e24d598STony Nguyen 	int result;
3011b8f15b6SMichal Swiatkowski 	LIST_HEAD(tmp_list);
3021b8f15b6SMichal Swiatkowski 
3031b8f15b6SMichal Swiatkowski 	eth_broadcast_addr(broadcast);
3041b8f15b6SMichal Swiatkowski 	if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) ||
3051b8f15b6SMichal Swiatkowski 	    ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) {
3061b8f15b6SMichal Swiatkowski 		ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
307*d54699e2STony Nguyen 		return -ENOMEM;
3081b8f15b6SMichal Swiatkowski 	}
3091b8f15b6SMichal Swiatkowski 
3101b8f15b6SMichal Swiatkowski 	result = mac_action(vsi, &tmp_list);
3111b8f15b6SMichal Swiatkowski 	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
3121b8f15b6SMichal Swiatkowski 	return result;
3131b8f15b6SMichal Swiatkowski }
3141b8f15b6SMichal Swiatkowski 
3151b8f15b6SMichal Swiatkowski /**
3161b8f15b6SMichal Swiatkowski  * ice_fltr_prepare_vlan - add or remove VLAN filter
3171b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
3181b8f15b6SMichal Swiatkowski  * @vlan_id: VLAN ID to add
3191b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
3201b8f15b6SMichal Swiatkowski  * @vlan_action: pointer to add or remove VLAN function
3211b8f15b6SMichal Swiatkowski  */
3225e24d598STony Nguyen static int
3231b8f15b6SMichal Swiatkowski ice_fltr_prepare_vlan(struct ice_vsi *vsi, u16 vlan_id,
3241b8f15b6SMichal Swiatkowski 		      enum ice_sw_fwd_act_type action,
3255e24d598STony Nguyen 		      int (*vlan_action)(struct ice_vsi *, struct list_head *))
3261b8f15b6SMichal Swiatkowski {
3275e24d598STony Nguyen 	int result;
3281b8f15b6SMichal Swiatkowski 	LIST_HEAD(tmp_list);
3291b8f15b6SMichal Swiatkowski 
3301b8f15b6SMichal Swiatkowski 	if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan_id, action))
331*d54699e2STony Nguyen 		return -ENOMEM;
3321b8f15b6SMichal Swiatkowski 
3331b8f15b6SMichal Swiatkowski 	result = vlan_action(vsi, &tmp_list);
3341b8f15b6SMichal Swiatkowski 	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
3351b8f15b6SMichal Swiatkowski 	return result;
3361b8f15b6SMichal Swiatkowski }
3371b8f15b6SMichal Swiatkowski 
3381b8f15b6SMichal Swiatkowski /**
3391b8f15b6SMichal Swiatkowski  * ice_fltr_prepare_eth - add or remove ethertype filter
3401b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
3411b8f15b6SMichal Swiatkowski  * @ethertype: ethertype of packet to be filtered
3421b8f15b6SMichal Swiatkowski  * @flag: direction of packet, Tx or Rx
3431b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
3441b8f15b6SMichal Swiatkowski  * @eth_action: pointer to add or remove ethertype function
3451b8f15b6SMichal Swiatkowski  */
3465e24d598STony Nguyen static int
3471b8f15b6SMichal Swiatkowski ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
3481b8f15b6SMichal Swiatkowski 		     enum ice_sw_fwd_act_type action,
3495e24d598STony Nguyen 		     int (*eth_action)(struct ice_vsi *, struct list_head *))
3501b8f15b6SMichal Swiatkowski {
3515e24d598STony Nguyen 	int result;
3521b8f15b6SMichal Swiatkowski 	LIST_HEAD(tmp_list);
3531b8f15b6SMichal Swiatkowski 
3541b8f15b6SMichal Swiatkowski 	if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action))
355*d54699e2STony Nguyen 		return -ENOMEM;
3561b8f15b6SMichal Swiatkowski 
3571b8f15b6SMichal Swiatkowski 	result = eth_action(vsi, &tmp_list);
3581b8f15b6SMichal Swiatkowski 	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
3591b8f15b6SMichal Swiatkowski 	return result;
3601b8f15b6SMichal Swiatkowski }
3611b8f15b6SMichal Swiatkowski 
3621b8f15b6SMichal Swiatkowski /**
3631b8f15b6SMichal Swiatkowski  * ice_fltr_add_mac - add single MAC filter
3641b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
3651b8f15b6SMichal Swiatkowski  * @mac: MAC to add
3661b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
3671b8f15b6SMichal Swiatkowski  */
3685e24d598STony Nguyen int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac,
3691b8f15b6SMichal Swiatkowski 		     enum ice_sw_fwd_act_type action)
3701b8f15b6SMichal Swiatkowski {
3711b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list);
3721b8f15b6SMichal Swiatkowski }
3731b8f15b6SMichal Swiatkowski 
3741b8f15b6SMichal Swiatkowski /**
3751b8f15b6SMichal Swiatkowski  * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast
3761b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
3771b8f15b6SMichal Swiatkowski  * @mac: MAC to add
3781b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
3791b8f15b6SMichal Swiatkowski  */
3805e24d598STony Nguyen int
3811b8f15b6SMichal Swiatkowski ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
3821b8f15b6SMichal Swiatkowski 			       enum ice_sw_fwd_act_type action)
3831b8f15b6SMichal Swiatkowski {
3841b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action,
3851b8f15b6SMichal Swiatkowski 						  ice_fltr_add_mac_list);
3861b8f15b6SMichal Swiatkowski }
3871b8f15b6SMichal Swiatkowski 
3881b8f15b6SMichal Swiatkowski /**
3891b8f15b6SMichal Swiatkowski  * ice_fltr_remove_mac - remove MAC filter
3901b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
3911b8f15b6SMichal Swiatkowski  * @mac: filter MAC to remove
3921b8f15b6SMichal Swiatkowski  * @action: action to remove
3931b8f15b6SMichal Swiatkowski  */
3945e24d598STony Nguyen int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,
3951b8f15b6SMichal Swiatkowski 			enum ice_sw_fwd_act_type action)
3961b8f15b6SMichal Swiatkowski {
3971b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list);
3981b8f15b6SMichal Swiatkowski }
3991b8f15b6SMichal Swiatkowski 
4001b8f15b6SMichal Swiatkowski /**
4011b8f15b6SMichal Swiatkowski  * ice_fltr_add_vlan - add single VLAN filter
4021b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
4031b8f15b6SMichal Swiatkowski  * @vlan_id: VLAN ID to add
4041b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
4051b8f15b6SMichal Swiatkowski  */
4065e24d598STony Nguyen int ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vlan_id,
4071b8f15b6SMichal Swiatkowski 		      enum ice_sw_fwd_act_type action)
4081b8f15b6SMichal Swiatkowski {
4091b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_vlan(vsi, vlan_id, action,
4101b8f15b6SMichal Swiatkowski 				     ice_fltr_add_vlan_list);
4111b8f15b6SMichal Swiatkowski }
4121b8f15b6SMichal Swiatkowski 
4131b8f15b6SMichal Swiatkowski /**
4141b8f15b6SMichal Swiatkowski  * ice_fltr_remove_vlan - remove VLAN filter
4151b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
4161b8f15b6SMichal Swiatkowski  * @vlan_id: filter VLAN to remove
4171b8f15b6SMichal Swiatkowski  * @action: action to remove
4181b8f15b6SMichal Swiatkowski  */
4195e24d598STony Nguyen int ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vlan_id,
4201b8f15b6SMichal Swiatkowski 			 enum ice_sw_fwd_act_type action)
4211b8f15b6SMichal Swiatkowski {
4221b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_vlan(vsi, vlan_id, action,
4231b8f15b6SMichal Swiatkowski 				     ice_fltr_remove_vlan_list);
4241b8f15b6SMichal Swiatkowski }
4251b8f15b6SMichal Swiatkowski 
4261b8f15b6SMichal Swiatkowski /**
4271b8f15b6SMichal Swiatkowski  * ice_fltr_add_eth - add specyfic ethertype filter
4281b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
4291b8f15b6SMichal Swiatkowski  * @ethertype: ethertype of filter
4301b8f15b6SMichal Swiatkowski  * @flag: direction of packet to be filtered, Tx or Rx
4311b8f15b6SMichal Swiatkowski  * @action: action to be performed on filter match
4321b8f15b6SMichal Swiatkowski  */
4335e24d598STony Nguyen int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
4341b8f15b6SMichal Swiatkowski 		     enum ice_sw_fwd_act_type action)
4351b8f15b6SMichal Swiatkowski {
4361b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
4371b8f15b6SMichal Swiatkowski 				    ice_fltr_add_eth_list);
4381b8f15b6SMichal Swiatkowski }
4391b8f15b6SMichal Swiatkowski 
4401b8f15b6SMichal Swiatkowski /**
4411b8f15b6SMichal Swiatkowski  * ice_fltr_remove_eth - remove ethertype filter
4421b8f15b6SMichal Swiatkowski  * @vsi: pointer to VSI struct
4431b8f15b6SMichal Swiatkowski  * @ethertype: ethertype of filter
4441b8f15b6SMichal Swiatkowski  * @flag: direction of filter
4451b8f15b6SMichal Swiatkowski  * @action: action to remove
4461b8f15b6SMichal Swiatkowski  */
4475e24d598STony Nguyen int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
4485e24d598STony Nguyen 			enum ice_sw_fwd_act_type action)
4491b8f15b6SMichal Swiatkowski {
4501b8f15b6SMichal Swiatkowski 	return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
4511b8f15b6SMichal Swiatkowski 				    ice_fltr_remove_eth_list);
4521b8f15b6SMichal Swiatkowski }
453bd676b29SMichal Swiatkowski 
454bd676b29SMichal Swiatkowski /**
455bd676b29SMichal Swiatkowski  * ice_fltr_update_rule_flags - update lan_en/lb_en flags
456bd676b29SMichal Swiatkowski  * @hw: pointer to hw
457bd676b29SMichal Swiatkowski  * @rule_id: id of rule being updated
458bd676b29SMichal Swiatkowski  * @recipe_id: recipe id of rule
459bd676b29SMichal Swiatkowski  * @act: current action field
460bd676b29SMichal Swiatkowski  * @type: Rx or Tx
461bd676b29SMichal Swiatkowski  * @src: source VSI
462bd676b29SMichal Swiatkowski  * @new_flags: combinations of lb_en and lan_en
463bd676b29SMichal Swiatkowski  */
4645e24d598STony Nguyen static int
465bd676b29SMichal Swiatkowski ice_fltr_update_rule_flags(struct ice_hw *hw, u16 rule_id, u16 recipe_id,
466bd676b29SMichal Swiatkowski 			   u32 act, u16 type, u16 src, u32 new_flags)
467bd676b29SMichal Swiatkowski {
468bd676b29SMichal Swiatkowski 	struct ice_aqc_sw_rules_elem *s_rule;
4695e24d598STony Nguyen 	int err;
470bd676b29SMichal Swiatkowski 	u32 flags_mask;
471bd676b29SMichal Swiatkowski 
472bd676b29SMichal Swiatkowski 	s_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL);
473bd676b29SMichal Swiatkowski 	if (!s_rule)
474*d54699e2STony Nguyen 		return -ENOMEM;
475bd676b29SMichal Swiatkowski 
476bd676b29SMichal Swiatkowski 	flags_mask = ICE_SINGLE_ACT_LB_ENABLE | ICE_SINGLE_ACT_LAN_ENABLE;
477bd676b29SMichal Swiatkowski 	act &= ~flags_mask;
478bd676b29SMichal Swiatkowski 	act |= (flags_mask & new_flags);
479bd676b29SMichal Swiatkowski 
480bd676b29SMichal Swiatkowski 	s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(recipe_id);
481bd676b29SMichal Swiatkowski 	s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(rule_id);
482bd676b29SMichal Swiatkowski 	s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
483bd676b29SMichal Swiatkowski 
484bd676b29SMichal Swiatkowski 	if (type & ICE_FLTR_RX) {
485bd676b29SMichal Swiatkowski 		s_rule->pdata.lkup_tx_rx.src =
486bd676b29SMichal Swiatkowski 			cpu_to_le16(hw->port_info->lport);
487bd676b29SMichal Swiatkowski 		s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
488bd676b29SMichal Swiatkowski 
489bd676b29SMichal Swiatkowski 	} else {
490bd676b29SMichal Swiatkowski 		s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(src);
491bd676b29SMichal Swiatkowski 		s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
492bd676b29SMichal Swiatkowski 	}
493bd676b29SMichal Swiatkowski 
494bd676b29SMichal Swiatkowski 	err = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
495bd676b29SMichal Swiatkowski 			      ice_aqc_opc_update_sw_rules, NULL);
496bd676b29SMichal Swiatkowski 
497bd676b29SMichal Swiatkowski 	kfree(s_rule);
498bd676b29SMichal Swiatkowski 	return err;
499bd676b29SMichal Swiatkowski }
500bd676b29SMichal Swiatkowski 
501bd676b29SMichal Swiatkowski /**
502bd676b29SMichal Swiatkowski  * ice_fltr_build_action - build action for rule
503bd676b29SMichal Swiatkowski  * @vsi_id: id of VSI which is use to build action
504bd676b29SMichal Swiatkowski  */
505bd676b29SMichal Swiatkowski static u32 ice_fltr_build_action(u16 vsi_id)
506bd676b29SMichal Swiatkowski {
507bd676b29SMichal Swiatkowski 	return ((vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M) |
508bd676b29SMichal Swiatkowski 		ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
509bd676b29SMichal Swiatkowski }
510bd676b29SMichal Swiatkowski 
511bd676b29SMichal Swiatkowski /**
512bd676b29SMichal Swiatkowski  * ice_fltr_update_flags_dflt_rule - update flags on default rule
513bd676b29SMichal Swiatkowski  * @vsi: pointer to VSI
514bd676b29SMichal Swiatkowski  * @rule_id: id of rule
515bd676b29SMichal Swiatkowski  * @direction: Tx or Rx
516bd676b29SMichal Swiatkowski  * @new_flags: flags to update
517bd676b29SMichal Swiatkowski  *
518bd676b29SMichal Swiatkowski  * Function updates flags on default rule with ICE_SW_LKUP_DFLT.
519bd676b29SMichal Swiatkowski  *
520bd676b29SMichal Swiatkowski  * Flags should be a combination of ICE_SINGLE_ACT_LB_ENABLE and
521bd676b29SMichal Swiatkowski  * ICE_SINGLE_ACT_LAN_ENABLE.
522bd676b29SMichal Swiatkowski  */
5235e24d598STony Nguyen int
524bd676b29SMichal Swiatkowski ice_fltr_update_flags_dflt_rule(struct ice_vsi *vsi, u16 rule_id, u8 direction,
525bd676b29SMichal Swiatkowski 				u32 new_flags)
526bd676b29SMichal Swiatkowski {
527bd676b29SMichal Swiatkowski 	u32 action = ice_fltr_build_action(vsi->vsi_num);
528bd676b29SMichal Swiatkowski 	struct ice_hw *hw = &vsi->back->hw;
529bd676b29SMichal Swiatkowski 
530bd676b29SMichal Swiatkowski 	return ice_fltr_update_rule_flags(hw, rule_id, ICE_SW_LKUP_DFLT, action,
531bd676b29SMichal Swiatkowski 					  direction, vsi->vsi_num, new_flags);
532bd676b29SMichal Swiatkowski }
533