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 /* 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 list 220 * @vsi: pointer to VSI struct 221 * @list: list to add filter info to 222 * @mac: MAC address to add 223 * @action: filter action 224 */ 225 int 226 ice_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 list 245 * @vsi: pointer to VSI struct 246 * @list: list to add filter info to 247 * @vlan: VLAN filter details 248 */ 249 static int 250 ice_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 list 270 * @vsi: pointer to VSI struct 271 * @list: list to add filter info to 272 * @ethertype: ethertype of packet that matches filter 273 * @flag: filter direction, Tx or Rx 274 * @action: filter action 275 */ 276 static int 277 ice_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 else 292 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 rule 300 * @vsi: pointer to VSI struct 301 * @mac: MAC address to add 302 * @action: action to be performed on filter match 303 * @mac_action: pointer to add or remove MAC function 304 */ 305 static int 306 ice_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 filter 325 * @vsi: pointer to VSI struct 326 * @mac: MAC address to add 327 * @action: action to be performed on filter match 328 * @mac_action: pointer to add or remove MAC function 329 */ 330 static int 331 ice_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 filter 354 * @vsi: pointer to VSI struct 355 * @vlan: VLAN filter details 356 * @vlan_action: pointer to add or remove VLAN function 357 */ 358 static int 359 ice_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 filter 375 * @vsi: pointer to VSI struct 376 * @ethertype: ethertype of packet to be filtered 377 * @flag: direction of packet, Tx or Rx 378 * @action: action to be performed on filter match 379 * @eth_action: pointer to add or remove ethertype function 380 */ 381 static int 382 ice_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 filter 399 * @vsi: pointer to VSI struct 400 * @mac: MAC to add 401 * @action: action to be performed on filter match 402 */ 403 int 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 broadcast 411 * @vsi: pointer to VSI struct 412 * @mac: MAC to add 413 * @action: action to be performed on filter match 414 */ 415 int 416 ice_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 filter 425 * @vsi: pointer to VSI struct 426 * @mac: filter MAC to remove 427 * @action: action to remove 428 */ 429 int 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 filter 437 * @vsi: pointer to VSI struct 438 * @vlan: VLAN filter details 439 */ 440 int 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 filter 447 * @vsi: pointer to VSI struct 448 * @vlan: VLAN filter details 449 */ 450 int 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 filter 457 * @vsi: pointer to VSI struct 458 * @ethertype: ethertype of filter 459 * @flag: direction of packet to be filtered, Tx or Rx 460 * @action: action to be performed on filter match 461 */ 462 int 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 filter 471 * @vsi: pointer to VSI struct 472 * @ethertype: ethertype of filter 473 * @flag: direction of filter 474 * @action: action to remove 475 */ 476 int 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