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 */ 15 void 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 */ 31 static int 32 ice_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_promisc 51 * @hw: pointer to the hardware structure 52 * @vsi: the VSI being configured 53 * @promisc_mask: mask of promiscuous config bits 54 * 55 * Set VSI with all associated VLANs to given promiscuous mode(s) 56 */ 57 int 58 ice_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_promisc 75 * @hw: pointer to the hardware structure 76 * @vsi: the VSI being configured 77 * @promisc_mask: mask of promiscuous config bits 78 * 79 * Clear VSI with all associated VLANs to given promiscuous mode(s) 80 */ 81 int 82 ice_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 structure 100 * @vsi_handle: VSI handle to clear mode 101 * @promisc_mask: mask of promiscuous config bits to clear 102 * @vid: VLAN ID to clear VLAN promiscuous 103 */ 104 int 105 ice_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 structure 123 * @vsi_handle: VSI handle to configure 124 * @promisc_mask: mask of promiscuous config bits 125 * @vid: VLAN ID to set VLAN promiscuous 126 */ 127 int 128 ice_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 filters 145 * @vsi: pointer to VSI struct 146 * @list: list of filters 147 */ 148 int 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 filters 155 * @vsi: pointer to VSI struct 156 * @list: list of filters 157 */ 158 int 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 filters 165 * @vsi: pointer to VSI struct 166 * @list: list of filters 167 */ 168 static 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 filters 175 * @vsi: pointer to VSI struct 176 * @list: list of filters 177 */ 178 static int 179 ice_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 filters 186 * @vsi: pointer to VSI struct 187 * @list: list of filters 188 */ 189 static 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 filters 196 * @vsi: pointer to VSI struct 197 * @list: list of filters 198 */ 199 static 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 VSI 206 * @vsi: pointer to VSI struct 207 */ 208 void ice_fltr_remove_all(struct ice_vsi *vsi) 209 { 210 ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx); 211 } 212 213 /** 214 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list 215 * @vsi: pointer to VSI struct 216 * @list: list to add filter info to 217 * @mac: MAC address to add 218 * @action: filter action 219 */ 220 int 221 ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list, 222 const u8 *mac, enum ice_sw_fwd_act_type action) 223 { 224 struct ice_fltr_info info = { 0 }; 225 226 info.flag = ICE_FLTR_TX; 227 info.src_id = ICE_SRC_ID_VSI; 228 info.lkup_type = ICE_SW_LKUP_MAC; 229 info.fltr_act = action; 230 info.vsi_handle = vsi->idx; 231 232 ether_addr_copy(info.l_data.mac.mac_addr, mac); 233 234 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 235 list); 236 } 237 238 /** 239 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list 240 * @vsi: pointer to VSI struct 241 * @list: list to add filter info to 242 * @vlan: VLAN filter details 243 */ 244 static int 245 ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list, 246 struct ice_vlan *vlan) 247 { 248 struct ice_fltr_info info = { 0 }; 249 250 info.flag = ICE_FLTR_TX; 251 info.src_id = ICE_SRC_ID_VSI; 252 info.lkup_type = ICE_SW_LKUP_VLAN; 253 info.fltr_act = ICE_FWD_TO_VSI; 254 info.vsi_handle = vsi->idx; 255 info.l_data.vlan.vlan_id = vlan->vid; 256 info.l_data.vlan.tpid = vlan->tpid; 257 info.l_data.vlan.tpid_valid = true; 258 259 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 260 list); 261 } 262 263 /** 264 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list 265 * @vsi: pointer to VSI struct 266 * @list: list to add filter info to 267 * @ethertype: ethertype of packet that matches filter 268 * @flag: filter direction, Tx or Rx 269 * @action: filter action 270 */ 271 static int 272 ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list, 273 u16 ethertype, u16 flag, 274 enum ice_sw_fwd_act_type action) 275 { 276 struct ice_fltr_info info = { 0 }; 277 278 info.flag = flag; 279 info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 280 info.fltr_act = action; 281 info.vsi_handle = vsi->idx; 282 info.l_data.ethertype_mac.ethertype = ethertype; 283 284 if (flag == ICE_FLTR_TX) 285 info.src_id = ICE_SRC_ID_VSI; 286 else 287 info.src_id = ICE_SRC_ID_LPORT; 288 289 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 290 list); 291 } 292 293 /** 294 * ice_fltr_prepare_mac - add or remove MAC rule 295 * @vsi: pointer to VSI struct 296 * @mac: MAC address to add 297 * @action: action to be performed on filter match 298 * @mac_action: pointer to add or remove MAC function 299 */ 300 static int 301 ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac, 302 enum ice_sw_fwd_act_type action, 303 int (*mac_action)(struct ice_vsi *, struct list_head *)) 304 { 305 LIST_HEAD(tmp_list); 306 int result; 307 308 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) { 309 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 310 return -ENOMEM; 311 } 312 313 result = mac_action(vsi, &tmp_list); 314 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 315 return result; 316 } 317 318 /** 319 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter 320 * @vsi: pointer to VSI struct 321 * @mac: MAC address to add 322 * @action: action to be performed on filter match 323 * @mac_action: pointer to add or remove MAC function 324 */ 325 static int 326 ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 327 enum ice_sw_fwd_act_type action, 328 int(*mac_action) 329 (struct ice_vsi *, struct list_head *)) 330 { 331 u8 broadcast[ETH_ALEN]; 332 LIST_HEAD(tmp_list); 333 int result; 334 335 eth_broadcast_addr(broadcast); 336 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) || 337 ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) { 338 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 339 return -ENOMEM; 340 } 341 342 result = mac_action(vsi, &tmp_list); 343 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 344 return result; 345 } 346 347 /** 348 * ice_fltr_prepare_vlan - add or remove VLAN filter 349 * @vsi: pointer to VSI struct 350 * @vlan: VLAN filter details 351 * @vlan_action: pointer to add or remove VLAN function 352 */ 353 static int 354 ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan, 355 int (*vlan_action)(struct ice_vsi *, struct list_head *)) 356 { 357 LIST_HEAD(tmp_list); 358 int result; 359 360 if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan)) 361 return -ENOMEM; 362 363 result = vlan_action(vsi, &tmp_list); 364 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 365 return result; 366 } 367 368 /** 369 * ice_fltr_prepare_eth - add or remove ethertype filter 370 * @vsi: pointer to VSI struct 371 * @ethertype: ethertype of packet to be filtered 372 * @flag: direction of packet, Tx or Rx 373 * @action: action to be performed on filter match 374 * @eth_action: pointer to add or remove ethertype function 375 */ 376 static int 377 ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 378 enum ice_sw_fwd_act_type action, 379 int (*eth_action)(struct ice_vsi *, struct list_head *)) 380 { 381 LIST_HEAD(tmp_list); 382 int result; 383 384 if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action)) 385 return -ENOMEM; 386 387 result = eth_action(vsi, &tmp_list); 388 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 389 return result; 390 } 391 392 /** 393 * ice_fltr_add_mac - add single MAC filter 394 * @vsi: pointer to VSI struct 395 * @mac: MAC to add 396 * @action: action to be performed on filter match 397 */ 398 int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac, 399 enum ice_sw_fwd_act_type action) 400 { 401 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list); 402 } 403 404 /** 405 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast 406 * @vsi: pointer to VSI struct 407 * @mac: MAC to add 408 * @action: action to be performed on filter match 409 */ 410 int 411 ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 412 enum ice_sw_fwd_act_type action) 413 { 414 return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action, 415 ice_fltr_add_mac_list); 416 } 417 418 /** 419 * ice_fltr_remove_mac - remove MAC filter 420 * @vsi: pointer to VSI struct 421 * @mac: filter MAC to remove 422 * @action: action to remove 423 */ 424 int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac, 425 enum ice_sw_fwd_act_type action) 426 { 427 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list); 428 } 429 430 /** 431 * ice_fltr_add_vlan - add single VLAN filter 432 * @vsi: pointer to VSI struct 433 * @vlan: VLAN filter details 434 */ 435 int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 436 { 437 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list); 438 } 439 440 /** 441 * ice_fltr_remove_vlan - remove VLAN filter 442 * @vsi: pointer to VSI struct 443 * @vlan: VLAN filter details 444 */ 445 int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 446 { 447 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list); 448 } 449 450 /** 451 * ice_fltr_add_eth - add specyfic ethertype filter 452 * @vsi: pointer to VSI struct 453 * @ethertype: ethertype of filter 454 * @flag: direction of packet to be filtered, Tx or Rx 455 * @action: action to be performed on filter match 456 */ 457 int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 458 enum ice_sw_fwd_act_type action) 459 { 460 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 461 ice_fltr_add_eth_list); 462 } 463 464 /** 465 * ice_fltr_remove_eth - remove ethertype filter 466 * @vsi: pointer to VSI struct 467 * @ethertype: ethertype of filter 468 * @flag: direction of filter 469 * @action: action to remove 470 */ 471 int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 472 enum ice_sw_fwd_act_type action) 473 { 474 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 475 ice_fltr_remove_eth_list); 476 } 477