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