summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/i40e
diff options
context:
space:
mode:
authorJacob Keller <jacob.e.keller@intel.com>2016-10-05 18:30:38 +0200
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-10-31 22:26:40 +0100
commit4a2ce27bb5f291c38d8e49ef16899828289e4d3d (patch)
tree07a332e6ed3a2686b179bfbc5eed6f59401d9fbc /drivers/net/ethernet/intel/i40e
parenti40e: store MAC/VLAN filters in a hash with the MAC Address as key (diff)
downloadlinux-4a2ce27bb5f291c38d8e49ef16899828289e4d3d.tar.xz
linux-4a2ce27bb5f291c38d8e49ef16899828289e4d3d.zip
i40e: properly cleanup on allocation failure in i40e_sync_vsi_filters
Currently, we fail to correctly restore filters on the temporary add list when we fail to allocate memory either for deletion or addition. Replace calls to "goto out;" with calls to a new location that correctly handles memory allocation failures. Note that it is safe for us to call i40e_undo_filter_entries on the tmp_del_list even after we've deleted filters because at this point it will be empty, so we don't need to separate the logic for add and delete failure. Change-Id: Iee107fd219c6e03e2fd9645c2debf8e8384a8521 Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/i40e')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index ea4dc9f9c416..35f06ba6bc4e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1683,15 +1683,16 @@ static void i40e_set_rx_mode(struct net_device *netdev)
}
/**
- * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
- * @vsi: pointer to vsi struct
+ * i40e_undo_filter_entries - Undo the changes made to MAC filter entries
+ * @vsi: Pointer to VSI struct
* @from: Pointer to list which contains MAC filter entries - changes to
* those entries needs to be undone.
*
- * MAC filter entries from list were slated to be removed from device.
+ * MAC filter entries from list were slated to be sent to firmware, either for
+ * addition or deletion.
**/
-static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
- struct hlist_head *from)
+static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
+ struct hlist_head *from)
{
struct i40e_mac_filter *f;
struct hlist_node *h;
@@ -1840,14 +1841,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
list_size = filter_list_len *
sizeof(struct i40e_aqc_remove_macvlan_element_data);
del_list = kzalloc(list_size, GFP_ATOMIC);
- if (!del_list) {
- /* Undo VSI's MAC filter entry element updates */
- spin_lock_bh(&vsi->mac_filter_hash_lock);
- i40e_undo_del_filter_entries(vsi, &tmp_del_list);
- spin_unlock_bh(&vsi->mac_filter_hash_lock);
- retval = -ENOMEM;
- goto out;
- }
+ if (!del_list)
+ goto err_no_memory;
hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) {
cmd_flags = 0;
@@ -1924,10 +1919,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
list_size = filter_list_len *
sizeof(struct i40e_aqc_add_macvlan_element_data);
add_list = kzalloc(list_size, GFP_ATOMIC);
- if (!add_list) {
- retval = -ENOMEM;
- goto out;
- }
+ if (!add_list)
+ goto err_no_memory;
+
num_add = 0;
hlist_for_each_entry(f, &tmp_add_list, hlist) {
if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
@@ -2152,6 +2146,17 @@ out:
clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
return retval;
+
+err_no_memory:
+ /* Restore elements on the temporary add and delete lists */
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
+ i40e_undo_filter_entries(vsi, &tmp_del_list);
+ i40e_undo_filter_entries(vsi, &tmp_add_list);
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+ vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+ clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+ return -ENOMEM;
}
/**