brintos

brintos / linux-shallow public Read only

0
0
Text · 12.6 KiB · aff7a14 Raw
482 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2018-2020, Intel Corporation. */3 4#include "ice.h"5#include "ice_fltr.h"6 7/**8 * ice_fltr_free_list - free filter lists helper9 * @dev: pointer to the device struct10 * @h: pointer to the list head to be freed11 *12 * Helper function to free filter lists previously created using13 * ice_fltr_add_mac_to_list14 */15void ice_fltr_free_list(struct device *dev, struct list_head *h)16{17	struct ice_fltr_list_entry *e, *tmp;18 19	list_for_each_entry_safe(e, tmp, h, list_entry) {20		list_del(&e->list_entry);21		devm_kfree(dev, e);22	}23}24 25/**26 * ice_fltr_add_entry_to_list - allocate and add filter entry to list27 * @dev: pointer to device needed by alloc function28 * @info: filter info struct that gets added to the passed in list29 * @list: pointer to the list which contains MAC filters entry30 */31static int32ice_fltr_add_entry_to_list(struct device *dev, struct ice_fltr_info *info,33			   struct list_head *list)34{35	struct ice_fltr_list_entry *entry;36 37	entry = devm_kzalloc(dev, sizeof(*entry), GFP_ATOMIC);38	if (!entry)39		return -ENOMEM;40 41	entry->fltr_info = *info;42 43	INIT_LIST_HEAD(&entry->list_entry);44	list_add(&entry->list_entry, list);45 46	return 0;47}48 49/**50 * ice_fltr_set_vlan_vsi_promisc51 * @hw: pointer to the hardware structure52 * @vsi: the VSI being configured53 * @promisc_mask: mask of promiscuous config bits54 *55 * Set VSI with all associated VLANs to given promiscuous mode(s)56 */57int58ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,59			      u8 promisc_mask)60{61	struct ice_pf *pf = hw->back;62	int result;63 64	result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false);65	if (result && result != -EEXIST)66		dev_err(ice_pf_to_dev(pf),67			"Error setting promisc mode on VSI %i (rc=%d)\n",68			vsi->vsi_num, result);69 70	return result;71}72 73/**74 * ice_fltr_clear_vlan_vsi_promisc75 * @hw: pointer to the hardware structure76 * @vsi: the VSI being configured77 * @promisc_mask: mask of promiscuous config bits78 *79 * Clear VSI with all associated VLANs to given promiscuous mode(s)80 */81int82ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,83				u8 promisc_mask)84{85	struct ice_pf *pf = hw->back;86	int result;87 88	result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true);89	if (result && result != -EEXIST)90		dev_err(ice_pf_to_dev(pf),91			"Error clearing promisc mode on VSI %i (rc=%d)\n",92			vsi->vsi_num, result);93 94	return result;95}96 97/**98 * ice_fltr_clear_vsi_promisc - clear specified promiscuous mode(s)99 * @hw: pointer to the hardware structure100 * @vsi_handle: VSI handle to clear mode101 * @promisc_mask: mask of promiscuous config bits to clear102 * @vid: VLAN ID to clear VLAN promiscuous103 */104int105ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,106			   u16 vid)107{108	struct ice_pf *pf = hw->back;109	int result;110 111	result = ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid);112	if (result && result != -EEXIST)113		dev_err(ice_pf_to_dev(pf),114			"Error clearing promisc mode on VSI %i for VID %u (rc=%d)\n",115			ice_get_hw_vsi_num(hw, vsi_handle), vid, result);116 117	return result;118}119 120/**121 * ice_fltr_set_vsi_promisc - set given VSI to given promiscuous mode(s)122 * @hw: pointer to the hardware structure123 * @vsi_handle: VSI handle to configure124 * @promisc_mask: mask of promiscuous config bits125 * @vid: VLAN ID to set VLAN promiscuous126 */127int128ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,129			 u16 vid)130{131	struct ice_pf *pf = hw->back;132	int result;133 134	result = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid);135	if (result && result != -EEXIST)136		dev_err(ice_pf_to_dev(pf),137			"Error setting promisc mode on VSI %i for VID %u (rc=%d)\n",138			ice_get_hw_vsi_num(hw, vsi_handle), vid, result);139 140	return result;141}142 143/**144 * ice_fltr_add_mac_list - add list of MAC filters145 * @vsi: pointer to VSI struct146 * @list: list of filters147 */148int ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list)149{150	return ice_add_mac(&vsi->back->hw, list);151}152 153/**154 * ice_fltr_remove_mac_list - remove list of MAC filters155 * @vsi: pointer to VSI struct156 * @list: list of filters157 */158int ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list)159{160	return ice_remove_mac(&vsi->back->hw, list);161}162 163/**164 * ice_fltr_add_vlan_list - add list of VLAN filters165 * @vsi: pointer to VSI struct166 * @list: list of filters167 */168static int ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list)169{170	return ice_add_vlan(&vsi->back->hw, list);171}172 173/**174 * ice_fltr_remove_vlan_list - remove list of VLAN filters175 * @vsi: pointer to VSI struct176 * @list: list of filters177 */178static int179ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list)180{181	return ice_remove_vlan(&vsi->back->hw, list);182}183 184/**185 * ice_fltr_add_eth_list - add list of ethertype filters186 * @vsi: pointer to VSI struct187 * @list: list of filters188 */189static int ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list)190{191	return ice_add_eth_mac(&vsi->back->hw, list);192}193 194/**195 * ice_fltr_remove_eth_list - remove list of ethertype filters196 * @vsi: pointer to VSI struct197 * @list: list of filters198 */199static int ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list)200{201	return ice_remove_eth_mac(&vsi->back->hw, list);202}203 204/**205 * ice_fltr_remove_all - remove all filters associated with VSI206 * @vsi: pointer to VSI struct207 */208void ice_fltr_remove_all(struct ice_vsi *vsi)209{210	ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);211	/* sync netdev filters if exist */212	if (vsi->netdev) {213		__dev_uc_unsync(vsi->netdev, NULL);214		__dev_mc_unsync(vsi->netdev, NULL);215	}216}217 218/**219 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list220 * @vsi: pointer to VSI struct221 * @list: list to add filter info to222 * @mac: MAC address to add223 * @action: filter action224 */225int226ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list,227			 const u8 *mac, enum ice_sw_fwd_act_type action)228{229	struct ice_fltr_info info = { 0 };230 231	info.flag = ICE_FLTR_TX;232	info.src_id = ICE_SRC_ID_VSI;233	info.lkup_type = ICE_SW_LKUP_MAC;234	info.fltr_act = action;235	info.vsi_handle = vsi->idx;236 237	ether_addr_copy(info.l_data.mac.mac_addr, mac);238 239	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,240					  list);241}242 243/**244 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list245 * @vsi: pointer to VSI struct246 * @list: list to add filter info to247 * @vlan: VLAN filter details248 */249static int250ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list,251			  struct ice_vlan *vlan)252{253	struct ice_fltr_info info = { 0 };254 255	info.flag = ICE_FLTR_TX;256	info.src_id = ICE_SRC_ID_VSI;257	info.lkup_type = ICE_SW_LKUP_VLAN;258	info.fltr_act = ICE_FWD_TO_VSI;259	info.vsi_handle = vsi->idx;260	info.l_data.vlan.vlan_id = vlan->vid;261	info.l_data.vlan.tpid = vlan->tpid;262	info.l_data.vlan.tpid_valid = true;263 264	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,265					  list);266}267 268/**269 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list270 * @vsi: pointer to VSI struct271 * @list: list to add filter info to272 * @ethertype: ethertype of packet that matches filter273 * @flag: filter direction, Tx or Rx274 * @action: filter action275 */276static int277ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list,278			 u16 ethertype, u16 flag,279			 enum ice_sw_fwd_act_type action)280{281	struct ice_fltr_info info = { 0 };282 283	info.flag = flag;284	info.lkup_type = ICE_SW_LKUP_ETHERTYPE;285	info.fltr_act = action;286	info.vsi_handle = vsi->idx;287	info.l_data.ethertype_mac.ethertype = ethertype;288 289	if (flag == ICE_FLTR_TX)290		info.src_id = ICE_SRC_ID_VSI;291	else292		info.src_id = ICE_SRC_ID_LPORT;293 294	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,295					  list);296}297 298/**299 * ice_fltr_prepare_mac - add or remove MAC rule300 * @vsi: pointer to VSI struct301 * @mac: MAC address to add302 * @action: action to be performed on filter match303 * @mac_action: pointer to add or remove MAC function304 */305static int306ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac,307		     enum ice_sw_fwd_act_type action,308		     int (*mac_action)(struct ice_vsi *, struct list_head *))309{310	LIST_HEAD(tmp_list);311	int result;312 313	if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) {314		ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);315		return -ENOMEM;316	}317 318	result = mac_action(vsi, &tmp_list);319	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);320	return result;321}322 323/**324 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter325 * @vsi: pointer to VSI struct326 * @mac: MAC address to add327 * @action: action to be performed on filter match328 * @mac_action: pointer to add or remove MAC function329 */330static int331ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,332				   enum ice_sw_fwd_act_type action,333				   int(*mac_action)334				   (struct ice_vsi *, struct list_head *))335{336	u8 broadcast[ETH_ALEN];337	LIST_HEAD(tmp_list);338	int result;339 340	eth_broadcast_addr(broadcast);341	if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) ||342	    ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) {343		ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);344		return -ENOMEM;345	}346 347	result = mac_action(vsi, &tmp_list);348	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);349	return result;350}351 352/**353 * ice_fltr_prepare_vlan - add or remove VLAN filter354 * @vsi: pointer to VSI struct355 * @vlan: VLAN filter details356 * @vlan_action: pointer to add or remove VLAN function357 */358static int359ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan,360		      int (*vlan_action)(struct ice_vsi *, struct list_head *))361{362	LIST_HEAD(tmp_list);363	int result;364 365	if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan))366		return -ENOMEM;367 368	result = vlan_action(vsi, &tmp_list);369	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);370	return result;371}372 373/**374 * ice_fltr_prepare_eth - add or remove ethertype filter375 * @vsi: pointer to VSI struct376 * @ethertype: ethertype of packet to be filtered377 * @flag: direction of packet, Tx or Rx378 * @action: action to be performed on filter match379 * @eth_action: pointer to add or remove ethertype function380 */381static int382ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,383		     enum ice_sw_fwd_act_type action,384		     int (*eth_action)(struct ice_vsi *, struct list_head *))385{386	LIST_HEAD(tmp_list);387	int result;388 389	if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action))390		return -ENOMEM;391 392	result = eth_action(vsi, &tmp_list);393	ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);394	return result;395}396 397/**398 * ice_fltr_add_mac - add single MAC filter399 * @vsi: pointer to VSI struct400 * @mac: MAC to add401 * @action: action to be performed on filter match402 */403int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac,404		     enum ice_sw_fwd_act_type action)405{406	return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list);407}408 409/**410 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast411 * @vsi: pointer to VSI struct412 * @mac: MAC to add413 * @action: action to be performed on filter match414 */415int416ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,417			       enum ice_sw_fwd_act_type action)418{419	return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action,420						  ice_fltr_add_mac_list);421}422 423/**424 * ice_fltr_remove_mac - remove MAC filter425 * @vsi: pointer to VSI struct426 * @mac: filter MAC to remove427 * @action: action to remove428 */429int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,430			enum ice_sw_fwd_act_type action)431{432	return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list);433}434 435/**436 * ice_fltr_add_vlan - add single VLAN filter437 * @vsi: pointer to VSI struct438 * @vlan: VLAN filter details439 */440int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)441{442	return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list);443}444 445/**446 * ice_fltr_remove_vlan - remove VLAN filter447 * @vsi: pointer to VSI struct448 * @vlan: VLAN filter details449 */450int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)451{452	return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list);453}454 455/**456 * ice_fltr_add_eth - add specyfic ethertype filter457 * @vsi: pointer to VSI struct458 * @ethertype: ethertype of filter459 * @flag: direction of packet to be filtered, Tx or Rx460 * @action: action to be performed on filter match461 */462int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,463		     enum ice_sw_fwd_act_type action)464{465	return ice_fltr_prepare_eth(vsi, ethertype, flag, action,466				    ice_fltr_add_eth_list);467}468 469/**470 * ice_fltr_remove_eth - remove ethertype filter471 * @vsi: pointer to VSI struct472 * @ethertype: ethertype of filter473 * @flag: direction of filter474 * @action: action to remove475 */476int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,477			enum ice_sw_fwd_act_type action)478{479	return ice_fltr_prepare_eth(vsi, ethertype, flag, action,480				    ice_fltr_remove_eth_list);481}482