1// SPDX-License-Identifier: GPL-2.0 2/* 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 helper 9 * @dev: pointer to the device struct 10 * @h: pointer to the list head to be freed 11 * 12 * Helper function to free filter lists previously created using 13 * ice_fltr_add_mac_to_list 14 */ 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 list 27 * @dev: pointer to device needed by alloc function 28 * @info: filter info struct that gets added to the passed in list 29 * @list: pointer to the list which contains MAC filters entry 30 */ 31static int 32ice_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_add_mac_list - add list of MAC filters 51 * @vsi: pointer to VSI struct 52 * @list: list of filters 53 */ 54enum ice_status 55ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list) 56{ 57 return ice_add_mac(&vsi->back->hw, list); 58} 59 60/** 61 * ice_fltr_remove_mac_list - remove list of MAC filters 62 * @vsi: pointer to VSI struct 63 * @list: list of filters 64 */ 65enum ice_status 66ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list) 67{ 68 return ice_remove_mac(&vsi->back->hw, list); 69} 70 71/** 72 * ice_fltr_add_vlan_list - add list of VLAN filters 73 * @vsi: pointer to VSI struct 74 * @list: list of filters 75 */ 76static enum ice_status 77ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list) 78{ 79 return ice_add_vlan(&vsi->back->hw, list); 80} 81 82/** 83 * ice_fltr_remove_vlan_list - remove list of VLAN filters 84 * @vsi: pointer to VSI struct 85 * @list: list of filters 86 */ 87static enum ice_status 88ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list) 89{ 90 return ice_remove_vlan(&vsi->back->hw, list); 91} 92 93/** 94 * ice_fltr_add_eth_list - add list of ethertype filters 95 * @vsi: pointer to VSI struct 96 * @list: list of filters 97 */ 98static enum ice_status 99ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list) 100{ 101 return ice_add_eth_mac(&vsi->back->hw, list); 102} 103 104/** 105 * ice_fltr_remove_eth_list - remove list of ethertype filters 106 * @vsi: pointer to VSI struct 107 * @list: list of filters 108 */ 109static enum ice_status 110ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list) 111{ 112 return ice_remove_eth_mac(&vsi->back->hw, list); 113} 114 115/** 116 * ice_fltr_remove_all - remove all filters associated with VSI 117 * @vsi: pointer to VSI struct 118 */ 119void ice_fltr_remove_all(struct ice_vsi *vsi) 120{ 121 ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx); 122} 123 124/** 125 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list 126 * @vsi: pointer to VSI struct 127 * @list: list to add filter info to 128 * @mac: MAC address to add 129 * @action: filter action 130 */ 131enum ice_status 132ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list, 133 const u8 *mac, enum ice_sw_fwd_act_type action) 134{ 135 struct ice_fltr_info info = { 0 }; 136 137 info.flag = ICE_FLTR_TX; 138 info.src_id = ICE_SRC_ID_VSI; 139 info.lkup_type = ICE_SW_LKUP_MAC; 140 info.fltr_act = action; 141 info.vsi_handle = vsi->idx; 142 143 ether_addr_copy(info.l_data.mac.mac_addr, mac); 144 145 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 146 list); 147} 148 149/** 150 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list 151 * @vsi: pointer to VSI struct 152 * @list: list to add filter info to 153 * @vlan_id: VLAN ID to add 154 * @action: filter action 155 */ 156static int 157ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list, 158 u16 vlan_id, enum ice_sw_fwd_act_type action) 159{ 160 struct ice_fltr_info info = { 0 }; 161 162 info.flag = ICE_FLTR_TX; 163 info.src_id = ICE_SRC_ID_VSI; 164 info.lkup_type = ICE_SW_LKUP_VLAN; 165 info.fltr_act = action; 166 info.vsi_handle = vsi->idx; 167 info.l_data.vlan.vlan_id = vlan_id; 168 169 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 170 list); 171} 172 173/** 174 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list 175 * @vsi: pointer to VSI struct 176 * @list: list to add filter info to 177 * @ethertype: ethertype of packet that matches filter 178 * @flag: filter direction, Tx or Rx 179 * @action: filter action 180 */ 181static int 182ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list, 183 u16 ethertype, u16 flag, 184 enum ice_sw_fwd_act_type action) 185{ 186 struct ice_fltr_info info = { 0 }; 187 188 info.flag = flag; 189 info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 190 info.fltr_act = action; 191 info.vsi_handle = vsi->idx; 192 info.l_data.ethertype_mac.ethertype = ethertype; 193 194 if (flag == ICE_FLTR_TX) 195 info.src_id = ICE_SRC_ID_VSI; 196 else 197 info.src_id = ICE_SRC_ID_LPORT; 198 199 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 200 list); 201} 202 203/** 204 * ice_fltr_prepare_mac - add or remove MAC rule 205 * @vsi: pointer to VSI struct 206 * @mac: MAC address to add 207 * @action: action to be performed on filter match 208 * @mac_action: pointer to add or remove MAC function 209 */ 210static enum ice_status 211ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac, 212 enum ice_sw_fwd_act_type action, 213 enum ice_status (*mac_action)(struct ice_vsi *, 214 struct list_head *)) 215{ 216 enum ice_status result; 217 LIST_HEAD(tmp_list); 218 219 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) { 220 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 221 return ICE_ERR_NO_MEMORY; 222 } 223 224 result = mac_action(vsi, &tmp_list); 225 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 226 return result; 227} 228 229/** 230 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter 231 * @vsi: pointer to VSI struct 232 * @mac: MAC address to add 233 * @action: action to be performed on filter match 234 * @mac_action: pointer to add or remove MAC function 235 */ 236static enum ice_status 237ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 238 enum ice_sw_fwd_act_type action, 239 enum ice_status(*mac_action) 240 (struct ice_vsi *, struct list_head *)) 241{ 242 u8 broadcast[ETH_ALEN]; 243 enum ice_status result; 244 LIST_HEAD(tmp_list); 245 246 eth_broadcast_addr(broadcast); 247 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) || 248 ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) { 249 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 250 return ICE_ERR_NO_MEMORY; 251 } 252 253 result = mac_action(vsi, &tmp_list); 254 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 255 return result; 256} 257 258/** 259 * ice_fltr_prepare_vlan - add or remove VLAN filter 260 * @vsi: pointer to VSI struct 261 * @vlan_id: VLAN ID to add 262 * @action: action to be performed on filter match 263 * @vlan_action: pointer to add or remove VLAN function 264 */ 265static enum ice_status 266ice_fltr_prepare_vlan(struct ice_vsi *vsi, u16 vlan_id, 267 enum ice_sw_fwd_act_type action, 268 enum ice_status (*vlan_action)(struct ice_vsi *, 269 struct list_head *)) 270{ 271 enum ice_status result; 272 LIST_HEAD(tmp_list); 273 274 if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan_id, action)) 275 return ICE_ERR_NO_MEMORY; 276 277 result = vlan_action(vsi, &tmp_list); 278 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 279 return result; 280} 281 282/** 283 * ice_fltr_prepare_eth - add or remove ethertype filter 284 * @vsi: pointer to VSI struct 285 * @ethertype: ethertype of packet to be filtered 286 * @flag: direction of packet, Tx or Rx 287 * @action: action to be performed on filter match 288 * @eth_action: pointer to add or remove ethertype function 289 */ 290static enum ice_status 291ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 292 enum ice_sw_fwd_act_type action, 293 enum ice_status (*eth_action)(struct ice_vsi *, 294 struct list_head *)) 295{ 296 enum ice_status result; 297 LIST_HEAD(tmp_list); 298 299 if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action)) 300 return ICE_ERR_NO_MEMORY; 301 302 result = eth_action(vsi, &tmp_list); 303 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 304 return result; 305} 306 307/** 308 * ice_fltr_add_mac - add single MAC filter 309 * @vsi: pointer to VSI struct 310 * @mac: MAC to add 311 * @action: action to be performed on filter match 312 */ 313enum ice_status ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac, 314 enum ice_sw_fwd_act_type action) 315{ 316 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list); 317} 318 319/** 320 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast 321 * @vsi: pointer to VSI struct 322 * @mac: MAC to add 323 * @action: action to be performed on filter match 324 */ 325enum ice_status 326ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 327 enum ice_sw_fwd_act_type action) 328{ 329 return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action, 330 ice_fltr_add_mac_list); 331} 332 333/** 334 * ice_fltr_remove_mac - remove MAC filter 335 * @vsi: pointer to VSI struct 336 * @mac: filter MAC to remove 337 * @action: action to remove 338 */ 339enum ice_status ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac, 340 enum ice_sw_fwd_act_type action) 341{ 342 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list); 343} 344 345/** 346 * ice_fltr_add_vlan - add single VLAN filter 347 * @vsi: pointer to VSI struct 348 * @vlan_id: VLAN ID to add 349 * @action: action to be performed on filter match 350 */ 351enum ice_status ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vlan_id, 352 enum ice_sw_fwd_act_type action) 353{ 354 return ice_fltr_prepare_vlan(vsi, vlan_id, action, 355 ice_fltr_add_vlan_list); 356} 357 358/** 359 * ice_fltr_remove_vlan - remove VLAN filter 360 * @vsi: pointer to VSI struct 361 * @vlan_id: filter VLAN to remove 362 * @action: action to remove 363 */ 364enum ice_status ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vlan_id, 365 enum ice_sw_fwd_act_type action) 366{ 367 return ice_fltr_prepare_vlan(vsi, vlan_id, action, 368 ice_fltr_remove_vlan_list); 369} 370 371/** 372 * ice_fltr_add_eth - add specyfic ethertype filter 373 * @vsi: pointer to VSI struct 374 * @ethertype: ethertype of filter 375 * @flag: direction of packet to be filtered, Tx or Rx 376 * @action: action to be performed on filter match 377 */ 378enum ice_status ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 379 enum ice_sw_fwd_act_type action) 380{ 381 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 382 ice_fltr_add_eth_list); 383} 384 385/** 386 * ice_fltr_remove_eth - remove ethertype filter 387 * @vsi: pointer to VSI struct 388 * @ethertype: ethertype of filter 389 * @flag: direction of filter 390 * @action: action to remove 391 */ 392enum ice_status ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, 393 u16 flag, enum ice_sw_fwd_act_type action) 394{ 395 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 396 ice_fltr_remove_eth_list); 397} 398