|
@@ -1271,10 +1271,13 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * i40e_del_filter - Remove a mac/vlan filter from the VSI
|
|
|
- * @vsi: the VSI to be searched
|
|
|
- * @macaddr: the MAC address
|
|
|
- * @vlan: the vlan
|
|
|
+ * __i40e_del_filter - Remove a specific filter from the VSI
|
|
|
+ * @vsi: VSI to remove from
|
|
|
+ * @f: the filter to remove from the list
|
|
|
+ *
|
|
|
+ * This function should be called instead of i40e_del_filter only if you know
|
|
|
+ * the exact filter you will remove already, such as via i40e_find_filter or
|
|
|
+ * i40e_find_mac.
|
|
|
*
|
|
|
* NOTE: This function is expected to be called with mac_filter_list_lock
|
|
|
* being held.
|
|
@@ -1282,14 +1285,8 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
|
|
|
* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
|
|
|
* instead of list_for_each_entry().
|
|
|
**/
|
|
|
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
|
|
|
+static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
|
|
|
{
|
|
|
- struct i40e_mac_filter *f;
|
|
|
-
|
|
|
- if (!vsi || !macaddr)
|
|
|
- return;
|
|
|
-
|
|
|
- f = i40e_find_filter(vsi, macaddr, vlan);
|
|
|
if (!f)
|
|
|
return;
|
|
|
|
|
@@ -1307,6 +1304,29 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * i40e_del_filter - Remove a MAC/VLAN filter from the VSI
|
|
|
+ * @vsi: the VSI to be searched
|
|
|
+ * @macaddr: the MAC address
|
|
|
+ * @vlan: the VLAN
|
|
|
+ *
|
|
|
+ * NOTE: This function is expected to be called with mac_filter_list_lock
|
|
|
+ * being held.
|
|
|
+ * ANOTHER NOTE: This function MUST be called from within the context of
|
|
|
+ * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
|
|
|
+ * instead of list_for_each_entry().
|
|
|
+ **/
|
|
|
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
|
|
|
+{
|
|
|
+ struct i40e_mac_filter *f;
|
|
|
+
|
|
|
+ if (!vsi || !macaddr)
|
|
|
+ return;
|
|
|
+
|
|
|
+ f = i40e_find_filter(vsi, macaddr, vlan);
|
|
|
+ __i40e_del_filter(vsi, f);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans
|
|
|
* @vsi: the VSI to be searched
|
|
@@ -1349,21 +1369,22 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
|
|
|
**/
|
|
|
int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr)
|
|
|
{
|
|
|
- struct i40e_mac_filter *f = NULL;
|
|
|
- int changed = 0;
|
|
|
+ struct i40e_mac_filter *f, *ftmp;
|
|
|
+ bool found = false;
|
|
|
|
|
|
WARN(!spin_is_locked(&vsi->mac_filter_list_lock),
|
|
|
"Missing mac_filter_list_lock\n");
|
|
|
- list_for_each_entry(f, &vsi->mac_filter_list, list) {
|
|
|
- if (ether_addr_equal(macaddr, f->macaddr))
|
|
|
- f->state = I40E_FILTER_REMOVE;
|
|
|
+ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
|
|
|
+ if (ether_addr_equal(macaddr, f->macaddr)) {
|
|
|
+ __i40e_del_filter(vsi, f);
|
|
|
+ found = true;
|
|
|
+ }
|
|
|
}
|
|
|
- if (changed) {
|
|
|
- vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
|
|
|
- vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
|
|
|
+
|
|
|
+ if (found)
|
|
|
return 0;
|
|
|
- }
|
|
|
- return -ENOENT;
|
|
|
+ else
|
|
|
+ return -ENOENT;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2256,7 +2277,7 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)
|
|
|
**/
|
|
|
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
|
|
|
{
|
|
|
- struct i40e_mac_filter *f, *ftmp, *add_f;
|
|
|
+ struct i40e_mac_filter *f, *ftmp, *add_f, *del_f;
|
|
|
|
|
|
/* Locked once because all functions invoked below iterates list*/
|
|
|
spin_lock_bh(&vsi->mac_filter_list_lock);
|
|
@@ -2290,11 +2311,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
|
|
|
* with 0, so we now accept untagged and specified tagged traffic
|
|
|
* (and not all tags along with untagged)
|
|
|
*/
|
|
|
- if (vid > 0) {
|
|
|
- if (vsi->netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr,
|
|
|
- I40E_VLAN_ANY)) {
|
|
|
- i40e_del_filter(vsi, vsi->netdev->dev_addr,
|
|
|
- I40E_VLAN_ANY);
|
|
|
+ if (vid > 0 && vsi->netdev) {
|
|
|
+ del_f = i40e_find_filter(vsi, vsi->netdev->dev_addr,
|
|
|
+ I40E_VLAN_ANY);
|
|
|
+ if (del_f) {
|
|
|
+ __i40e_del_filter(vsi, del_f);
|
|
|
add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0);
|
|
|
if (!add_f) {
|
|
|
dev_info(&vsi->back->pdev->dev,
|
|
@@ -2311,9 +2332,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
|
|
|
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
|
|
|
if (f->state == I40E_FILTER_REMOVE)
|
|
|
continue;
|
|
|
- if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY))
|
|
|
+ del_f = i40e_find_filter(vsi, f->macaddr,
|
|
|
+ I40E_VLAN_ANY);
|
|
|
+ if (!del_f)
|
|
|
continue;
|
|
|
- i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY);
|
|
|
+ __i40e_del_filter(vsi, del_f);
|
|
|
add_f = i40e_add_filter(vsi, f->macaddr, 0);
|
|
|
if (!add_f) {
|
|
|
dev_info(&vsi->back->pdev->dev,
|
|
@@ -2353,8 +2376,10 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
|
|
|
if (vsi->netdev)
|
|
|
i40e_del_filter(vsi, netdev->dev_addr, vid);
|
|
|
|
|
|
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
|
|
|
- i40e_del_filter(vsi, f->macaddr, vid);
|
|
|
+ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
|
|
|
+ if (f->vlan == vid)
|
|
|
+ __i40e_del_filter(vsi, f);
|
|
|
+ }
|
|
|
|
|
|
/* go through all the filters for this VSI and if there is only
|
|
|
* vid == 0 it means there are no other filters, so vid 0 must
|
|
@@ -2386,7 +2411,8 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
|
|
|
|
|
|
if (!filter_count) {
|
|
|
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
|
|
|
- i40e_del_filter(vsi, f->macaddr, 0);
|
|
|
+ if (!f->vlan)
|
|
|
+ __i40e_del_filter(vsi, f);
|
|
|
add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY);
|
|
|
if (!add_f) {
|
|
|
dev_info(&vsi->back->pdev->dev,
|
|
@@ -9455,7 +9481,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
|
|
|
|
|
|
/* make sure any remaining filters are marked for deletion */
|
|
|
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
|
|
|
- i40e_del_filter(vsi, f->macaddr, f->vlan);
|
|
|
+ __i40e_del_filter(vsi, f);
|
|
|
|
|
|
spin_unlock_bh(&vsi->mac_filter_list_lock);
|
|
|
|