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_add_mac_list - add list of MAC filters 51 * @vsi: pointer to VSI struct 52 * @list: list of filters 53 */ 54 enum ice_status 55 ice_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 */ 65 enum ice_status 66 ice_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 */ 76 static enum ice_status 77 ice_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 */ 87 static enum ice_status 88 ice_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 */ 98 static enum ice_status 99 ice_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 */ 109 static enum ice_status 110 ice_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 */ 119 void 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 */ 131 int 132 ice_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 */ 156 static int 157 ice_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 */ 181 static int 182 ice_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 */ 210 static enum ice_status 211 ice_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 */ 236 static enum ice_status 237 ice_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 */ 265 static enum ice_status 266 ice_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 */ 290 static enum ice_status 291 ice_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 */ 313 enum 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 */ 325 enum ice_status 326 ice_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 */ 339 enum 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 */ 351 enum 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 */ 364 enum 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 */ 378 enum 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 */ 392 enum 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 399 /** 400 * ice_fltr_update_rule_flags - update lan_en/lb_en flags 401 * @hw: pointer to hw 402 * @rule_id: id of rule being updated 403 * @recipe_id: recipe id of rule 404 * @act: current action field 405 * @type: Rx or Tx 406 * @src: source VSI 407 * @new_flags: combinations of lb_en and lan_en 408 */ 409 static enum ice_status 410 ice_fltr_update_rule_flags(struct ice_hw *hw, u16 rule_id, u16 recipe_id, 411 u32 act, u16 type, u16 src, u32 new_flags) 412 { 413 struct ice_aqc_sw_rules_elem *s_rule; 414 enum ice_status err; 415 u32 flags_mask; 416 417 s_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL); 418 if (!s_rule) 419 return ICE_ERR_NO_MEMORY; 420 421 flags_mask = ICE_SINGLE_ACT_LB_ENABLE | ICE_SINGLE_ACT_LAN_ENABLE; 422 act &= ~flags_mask; 423 act |= (flags_mask & new_flags); 424 425 s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(recipe_id); 426 s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(rule_id); 427 s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act); 428 429 if (type & ICE_FLTR_RX) { 430 s_rule->pdata.lkup_tx_rx.src = 431 cpu_to_le16(hw->port_info->lport); 432 s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); 433 434 } else { 435 s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(src); 436 s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); 437 } 438 439 err = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1, 440 ice_aqc_opc_update_sw_rules, NULL); 441 442 kfree(s_rule); 443 return err; 444 } 445 446 /** 447 * ice_fltr_build_action - build action for rule 448 * @vsi_id: id of VSI which is use to build action 449 */ 450 static u32 ice_fltr_build_action(u16 vsi_id) 451 { 452 return ((vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M) | 453 ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT; 454 } 455 456 /** 457 * ice_fltr_update_flags_dflt_rule - update flags on default rule 458 * @vsi: pointer to VSI 459 * @rule_id: id of rule 460 * @direction: Tx or Rx 461 * @new_flags: flags to update 462 * 463 * Function updates flags on default rule with ICE_SW_LKUP_DFLT. 464 * 465 * Flags should be a combination of ICE_SINGLE_ACT_LB_ENABLE and 466 * ICE_SINGLE_ACT_LAN_ENABLE. 467 */ 468 enum ice_status 469 ice_fltr_update_flags_dflt_rule(struct ice_vsi *vsi, u16 rule_id, u8 direction, 470 u32 new_flags) 471 { 472 u32 action = ice_fltr_build_action(vsi->vsi_num); 473 struct ice_hw *hw = &vsi->back->hw; 474 475 return ice_fltr_update_rule_flags(hw, rule_id, ICE_SW_LKUP_DFLT, action, 476 direction, vsi->vsi_num, new_flags); 477 } 478