i40e: properly delete VF MAC filters
authorMitch Williams <mitch.a.williams@intel.com>
Thu, 19 Nov 2015 19:34:16 +0000 (11:34 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sun, 13 Dec 2015 05:08:09 +0000 (21:08 -0800)
The virtual channel interface was using incorrect semantics to remove
MAC addresses, which would leave incorrect filters active when using
VLANs. To correct this, add a new function that unconditionally removes
MAC addresses from all VLANs, and call this function when the VF
requests a MAC filter removal.

Change-ID: I69826908ae4f6c847f5bf9b32f11faa760189c74
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c

index bd6d9c002accacd9dba8a1628291688e3352e2a1..b7bc014ae00b7b9e89a36c74c357618178ef1e16 100644 (file)
@@ -776,6 +776,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
 int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
 struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
                                             bool is_vf, bool is_netdev);
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
+                         bool is_vf, bool is_netdev);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
 struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
                                      bool is_vf, bool is_netdev);
index 3373b7506bedbc13020f19189b681e2d81b3564e..36d1c2bb0120ab2ffd80e2ab44de87e006b49619 100644 (file)
@@ -1258,6 +1258,42 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
                                        struct i40e_mac_filter, list);
 }
 
+/**
+ * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be removed
+ * @is_vf: true if it is a VF
+ * @is_netdev: true if it is a netdev
+ *
+ * Removes a given MAC address from a VSI, regardless of VLAN
+ *
+ * Returns 0 for success, or error
+ **/
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
+                         bool is_vf, bool is_netdev)
+{
+       struct i40e_mac_filter *f = NULL;
+       int changed = 0;
+
+       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)) &&
+                   (is_vf == f->is_vf) &&
+                   (is_netdev == f->is_netdev)) {
+                       f->counter--;
+                       f->changed = true;
+                       changed = 1;
+               }
+       }
+       if (changed) {
+               vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+               vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+               return 0;
+       }
+       return -ENOENT;
+}
+
 /**
  * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM
  * @vsi: the PF Main VSI - inappropriate for any other VSI
index b3bd81c3e1ceec5d704420adc966f966e10df98f..cbbb2ef4b256dae76a48f37b4902168de410f923 100644 (file)
@@ -1683,8 +1683,12 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        spin_lock_bh(&vsi->mac_filter_list_lock);
        /* delete addresses from the list */
        for (i = 0; i < al->num_elements; i++)
-               i40e_del_filter(vsi, al->list[i].addr,
-                               I40E_VLAN_ANY, true, false);
+               if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) {
+                       ret = I40E_ERR_INVALID_MAC_ADDR;
+                       spin_unlock_bh(&vsi->mac_filter_list_lock);
+                       goto error_param;
+               }
+
        spin_unlock_bh(&vsi->mac_filter_list_lock);
 
        /* program the updated filter list */