Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/702116/?format=api
{ "id": 702116, "url": "http://patchwork.ozlabs.org/api/patches/702116/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1480710782-9195-7-git-send-email-bimmy.pujari@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1480710782-9195-7-git-send-email-bimmy.pujari@intel.com>", "list_archive_url": null, "date": "2016-12-02T20:33:00", "name": "[next,S56,6/8] i40e: avoid race condition when sending filters to firmware for addition", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "641b4168d49ac91e333d32e28fbed8a9fe16c5d2", "submitter": { "id": 68919, "url": "http://patchwork.ozlabs.org/api/people/68919/?format=api", "name": "Pujari, Bimmy", "email": "bimmy.pujari@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1480710782-9195-7-git-send-email-bimmy.pujari@intel.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/702116/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/702116/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@lists.osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Received": [ "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3tVm9S5YWBz9t2n\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 3 Dec 2016 07:34:52 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 5725D850DB;\n\tFri, 2 Dec 2016 20:34:51 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id TlfRNcZK0rQO; Fri, 2 Dec 2016 20:34:47 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id DC0D18544C;\n\tFri, 2 Dec 2016 20:34:45 +0000 (UTC)", "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\tby ash.osuosl.org (Postfix) with ESMTP id 6569F1BFB36\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 2 Dec 2016 20:34:42 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 660258451E\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 2 Dec 2016 20:34:42 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id Dv7Shp9A1a+8 for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 2 Dec 2016 20:34:41 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby whitealder.osuosl.org (Postfix) with ESMTPS id 176C484519\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 2 Dec 2016 20:34:41 +0000 (UTC)", "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby fmsmga101.fm.intel.com with ESMTP; 02 Dec 2016 12:34:40 -0800", "from bimmy.jf.intel.com (HELO bimmy.linux1.jf.intel.com)\n\t([134.134.2.167])\n\tby orsmga001.jf.intel.com with ESMTP; 02 Dec 2016 12:34:39 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos; i=\"5.33,288,1477983600\"; d=\"scan'208\";\n\ta=\"1067223594\"", "From": "Bimmy Pujari <bimmy.pujari@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Fri, 2 Dec 2016 12:33:00 -0800", "Message-Id": "<1480710782-9195-7-git-send-email-bimmy.pujari@intel.com>", "X-Mailer": "git-send-email 2.4.11", "In-Reply-To": "<1480710782-9195-1-git-send-email-bimmy.pujari@intel.com>", "References": "<1480710782-9195-1-git-send-email-bimmy.pujari@intel.com>", "Subject": "[Intel-wired-lan] [next PATCH S56 6/8] i40e: avoid race condition\n\twhen sending filters to firmware for addition", "X-BeenThere": "intel-wired-lan@lists.osuosl.org", "X-Mailman-Version": "2.1.18-1", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>", "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>", "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>" }, "content": "From: Jacob Keller <jacob.e.keller@intel.com>\n\nRefactor how we add new filters to firmware to avoid a race condition\nthat can occur due to removing filters from the hash temporarily.\n\nTo understand the race condition, suppose that you have a number of MAC\nfilters, but have not yet added any VLANs. Now, add two VLANs in rapid\nsuccession. A possible resulting flow would look something like the\nfollowing:\n\n(1) lock hash for add VLAN\n(2) add the new MAC/VLAN combos for each current MAC filter\n(3) unlock hash\n(4) lock hash for filter sync\n(5) notice that we have a VLAN, so prepare to update all MAC filters\n with VLAN=-1 to be VLAN=0.\n(6) move NEW and REMOVE filters to temporary list\n(7) unlock hash\n(8) lock hash for add VLAN\n(9) add new MAC/VLAN combos. Notice that no MAC filters are currently in\n the hash list, so we don't add any VLANs <--- BUG!\n(10) unlock hash\n(11) sync the temporary lists to firmware\n(12) lock hash for post-sync\n(13) move the temporary elements back to the main list\n....\n\nBecause we take filters out of the main hash into temporary lists, we\nintroduce a narrow window where it is possible that other callers to the\nlist will not see some of the filters which were previously added but\nhave not yet been finalized. This results in sometimes dropping VLAN\nadditions, and could also result in failing to add a MAC address on the\nnewly added VLAN.\n\nOne obvious way to avoid this race condition would be to lock the entire\nfirmware process. Unfortunately this does not work because adminq\nfirmware commands take a mutex which results in a sleep while atomic\nBUG(). So, we can't use the simplest approach.\n\nAn alternative approach is to simply not remove the filters from the\nhash list while adding. Instead, add an i40e_new_mac_filter structure\nwhich we will use to track added filters. This avoids the need to remove\nthe filter from the hash list. We'll store a pointer to the original\ni40e_mac_filter, along with our own copy of the state.\n\nWe won't update the state directly, so as to avoid race with other code\nthat may modify the state while under the lock. We are safe to read\nf->macaddr and f->vlan since these only change in two locations. The\nfirst is on filter creation, which must have already occurred. The\nsecond is inside i40e_correct_vlan_filters which was previously run\nafter creation of this object and can't be run again until after. Thus,\nwe should be safe to read the MAC address and VLAN while outside the\nlock.\n\nWe also aren't going to run into a use-after-free issue because the only\nplace where we free filters is when they are marked FAILED or when we\nremove them inside the sync subtask. Since the subtask has its own\ncritical flag to prevent duplicate runs, we know this won't happen. We\nalso know that the only location to transition a filter from NEW to\nFAILED is inside the subtask also, so we aren't worried about that\neither.\n\nUse the wrapper i40e_new_mac_filter for additions, and once we've\nfinalized the addition to firmware, we will update the filter state\ninside a lock, and then free the wrapper structure.\n\nIn order to avoid a possible race condition with filter deletion, we\nwon't update the original filter state unless it is still\nI40E_FILTER_NEW when we finish the firmware sync.\n\nThis approach is more complex, but avoids race conditions related to\nfilters being temporarily removed from the list. We do not need the same\nbehavior for deletion because we always unconditionally removed the\nfilters from the list regardless of the firmware status.\n\nSigned-off-by: Jacob Keller <jacob.e.keller@intel.com>\nChange-Id: I14b74bc2301f8e69433fbe77ebca532db20c5317\n---\n drivers/net/ethernet/intel/i40e/i40e.h | 16 +++\n drivers/net/ethernet/intel/i40e/i40e_main.c | 147 ++++++++++++++++++----------\n 2 files changed, 112 insertions(+), 51 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex eb01dac..0f2bf241 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -506,6 +506,22 @@ struct i40e_mac_filter {\n \tenum i40e_filter_state state;\n };\n \n+/* Wrapper structure to keep track of filters while we are preparing to send\n+ * firmware commands. We cannot send firmware commands while holding a\n+ * spinlock, since it might sleep. To avoid this, we wrap the added filters in\n+ * a separate structure, which will track the state change and update the real\n+ * filter while under lock. We can't simply hold the filters in a separate\n+ * list, as this opens a window for a race condition when adding new MAC\n+ * addresses to all VLANs, or when adding new VLANs to all MAC addresses.\n+ */\n+struct i40e_new_mac_filter {\n+\tstruct hlist_node hlist;\n+\tstruct i40e_mac_filter *f;\n+\n+\t/* Track future changes to state separately */\n+\tenum i40e_filter_state state;\n+};\n+\n struct i40e_veb {\n \tstruct i40e_pf *pf;\n \tu16 idx;\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 827676e..69a51a4 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -1261,6 +1261,7 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,\n \t\t\t\t\t int vlan_filters)\n {\n \tstruct i40e_mac_filter *f, *add_head;\n+\tstruct i40e_new_mac_filter *new;\n \tstruct hlist_node *h;\n \tint bkt, new_vlan;\n \n@@ -1279,13 +1280,13 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,\n \t */\n \n \t/* Update the filters about to be added in place */\n-\thlist_for_each_entry(f, tmp_add_list, hlist) {\n-\t\tif (vsi->info.pvid && f->vlan != vsi->info.pvid)\n-\t\t\tf->vlan = vsi->info.pvid;\n-\t\telse if (vlan_filters && f->vlan == I40E_VLAN_ANY)\n-\t\t\tf->vlan = 0;\n-\t\telse if (!vlan_filters && f->vlan == 0)\n-\t\t\tf->vlan = I40E_VLAN_ANY;\n+\thlist_for_each_entry(new, tmp_add_list, hlist) {\n+\t\tif (vsi->info.pvid && new->f->vlan != vsi->info.pvid)\n+\t\t\tnew->f->vlan = vsi->info.pvid;\n+\t\telse if (vlan_filters && new->f->vlan == I40E_VLAN_ANY)\n+\t\t\tnew->f->vlan = 0;\n+\t\telse if (!vlan_filters && new->f->vlan == 0)\n+\t\t\tnew->f->vlan = I40E_VLAN_ANY;\n \t}\n \n \t/* Update the remaining active filters */\n@@ -1311,9 +1312,16 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,\n \t\t\tif (!add_head)\n \t\t\t\treturn -ENOMEM;\n \n-\t\t\t/* Put the replacement filter into the add list */\n-\t\t\thash_del(&add_head->hlist);\n-\t\t\thlist_add_head(&add_head->hlist, tmp_add_list);\n+\t\t\t/* Create a temporary i40e_new_mac_filter */\n+\t\t\tnew = kzalloc(sizeof(*new), GFP_ATOMIC);\n+\t\t\tif (!new)\n+\t\t\t\treturn -ENOMEM;\n+\n+\t\t\tnew->f = add_head;\n+\t\t\tnew->state = add_head->state;\n+\n+\t\t\t/* Add the new filter to the tmp list */\n+\t\t\thlist_add_head(&new->hlist, tmp_add_list);\n \n \t\t\t/* Put the original filter into the delete list */\n \t\t\tf->state = I40E_FILTER_REMOVE;\n@@ -1825,16 +1833,15 @@ static void i40e_set_rx_mode(struct net_device *netdev)\n }\n \n /**\n- * i40e_undo_filter_entries - Undo the changes made to MAC filter entries\n+ * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries\n * @vsi: Pointer to VSI struct\n * @from: Pointer to list which contains MAC filter entries - changes to\n * those entries needs to be undone.\n *\n- * MAC filter entries from list were slated to be sent to firmware, either for\n- * addition or deletion.\n+ * MAC filter entries from this list were slated for deletion.\n **/\n-static void i40e_undo_filter_entries(struct i40e_vsi *vsi,\n-\t\t\t\t struct hlist_head *from)\n+static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,\n+\t\t\t\t\t struct hlist_head *from)\n {\n \tstruct i40e_mac_filter *f;\n \tstruct hlist_node *h;\n@@ -1849,28 +1856,50 @@ static void i40e_undo_filter_entries(struct i40e_vsi *vsi,\n }\n \n /**\n+ * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries\n+ * @vsi: Pointer to vsi struct\n+ * @from: Pointer to list which contains MAC filter entries - changes to\n+ * those entries needs to be undone.\n+ *\n+ * MAC filter entries from this list were slated for addition.\n+ **/\n+static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi,\n+\t\t\t\t\t struct hlist_head *from)\n+{\n+\tstruct i40e_new_mac_filter *new;\n+\tstruct hlist_node *h;\n+\n+\thlist_for_each_entry_safe(new, h, from, hlist) {\n+\t\t/* We can simply free the wrapper structure */\n+\t\thlist_del(&new->hlist);\n+\t\tkfree(new);\n+\t}\n+}\n+\n+/**\n * i40e_next_entry - Get the next non-broadcast filter from a list\n- * @f: pointer to filter in list\n+ * @next: pointer to filter in list\n *\n * Returns the next non-broadcast filter in the list. Required so that we\n * ignore broadcast filters within the list, since these are not handled via\n * the normal firmware update path.\n */\n-static struct i40e_mac_filter *i40e_next_filter(struct i40e_mac_filter *f)\n+static\n+struct i40e_new_mac_filter *i40e_next_filter(struct i40e_new_mac_filter *next)\n {\n-\twhile (f) {\n-\t\tf = hlist_entry(f->hlist.next,\n-\t\t\t\ttypeof(struct i40e_mac_filter),\n-\t\t\t\thlist);\n+\twhile (next) {\n+\t\tnext = hlist_entry(next->hlist.next,\n+\t\t\t\t typeof(struct i40e_new_mac_filter),\n+\t\t\t\t hlist);\n \n \t\t/* keep going if we found a broadcast filter */\n-\t\tif (f && is_broadcast_ether_addr(f->macaddr))\n+\t\tif (next && is_broadcast_ether_addr(next->f->macaddr))\n \t\t\tcontinue;\n \n \t\tbreak;\n \t}\n \n-\treturn f;\n+\treturn next;\n }\n \n /**\n@@ -1886,7 +1915,7 @@ static struct i40e_mac_filter *i40e_next_filter(struct i40e_mac_filter *f)\n static int\n i40e_update_filter_state(int count,\n \t\t\t struct i40e_aqc_add_macvlan_element_data *add_list,\n-\t\t\t struct i40e_mac_filter *add_head)\n+\t\t\t struct i40e_new_mac_filter *add_head)\n {\n \tint retval = 0;\n \tint i;\n@@ -1964,7 +1993,7 @@ void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name,\n static\n void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,\n \t\t\t struct i40e_aqc_add_macvlan_element_data *list,\n-\t\t\t struct i40e_mac_filter *add_head,\n+\t\t\t struct i40e_new_mac_filter *add_head,\n \t\t\t int num_add, bool *promisc_changed)\n {\n \tstruct i40e_hw *hw = &vsi->back->hw;\n@@ -1992,10 +2021,12 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,\n * This function sets or clears the promiscuous broadcast flags for VLAN\n * filters in order to properly receive broadcast frames. Assumes that only\n * broadcast filters are passed.\n+ *\n+ * Returns status indicating success or failure;\n **/\n-static\n-void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,\n-\t\t\t struct i40e_mac_filter *f)\n+static i40e_status\n+i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,\n+\t\t\t struct i40e_mac_filter *f)\n {\n \tbool enable = f->state == I40E_FILTER_NEW;\n \tstruct i40e_hw *hw = &vsi->back->hw;\n@@ -2014,15 +2045,13 @@ void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,\n \t\t\t\t\t\t\t NULL);\n \t}\n \n-\tif (aq_ret) {\n+\tif (aq_ret)\n \t\tdev_warn(&vsi->back->pdev->dev,\n \t\t\t \"Error %s setting broadcast promiscuous mode on %s\\n\",\n \t\t\t i40e_aq_str(hw, hw->aq.asq_last_status),\n \t\t\t vsi_name);\n-\t\tf->state = I40E_FILTER_FAILED;\n-\t} else if (enable) {\n-\t\tf->state = I40E_FILTER_ACTIVE;\n-\t}\n+\n+\treturn aq_ret;\n }\n \n /**\n@@ -2036,7 +2065,8 @@ void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,\n int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n {\n \tstruct hlist_head tmp_add_list, tmp_del_list;\n-\tstruct i40e_mac_filter *f, *add_head = NULL;\n+\tstruct i40e_mac_filter *f;\n+\tstruct i40e_new_mac_filter *new, *add_head = NULL;\n \tstruct i40e_hw *hw = &vsi->back->hw;\n \tunsigned int failed_filters = 0;\n \tunsigned int vlan_filters = 0;\n@@ -2090,8 +2120,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (f->state == I40E_FILTER_NEW) {\n-\t\t\t\thash_del(&f->hlist);\n-\t\t\t\thlist_add_head(&f->hlist, &tmp_add_list);\n+\t\t\t\t/* Create a temporary i40e_new_mac_filter */\n+\t\t\t\tnew = kzalloc(sizeof(*new), GFP_ATOMIC);\n+\t\t\t\tif (!new)\n+\t\t\t\t\tgoto err_no_memory_locked;\n+\n+\t\t\t\t/* Store pointer to the real filter */\n+\t\t\t\tnew->f = f;\n+\t\t\t\tnew->state = f->state;\n+\n+\t\t\t\t/* Add it to the hash list */\n+\t\t\t\thlist_add_head(&new->hlist, &tmp_add_list);\n \t\t\t}\n \n \t\t\t/* Count the number of active (current and new) VLAN\n@@ -2184,32 +2223,37 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\tgoto err_no_memory;\n \n \t\tnum_add = 0;\n-\t\thlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {\n+\t\thlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {\n \t\t\tif (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,\n \t\t\t\t &vsi->state)) {\n-\t\t\t\tf->state = I40E_FILTER_FAILED;\n+\t\t\t\tnew->state = I40E_FILTER_FAILED;\n \t\t\t\tcontinue;\n \t\t\t}\n \n \t\t\t/* handle broadcast filters by updating the broadcast\n \t\t\t * promiscuous flag instead of adding a MAC filter.\n \t\t\t */\n-\t\t\tif (is_broadcast_ether_addr(f->macaddr)) {\n-\t\t\t\ti40e_aqc_broadcast_filter(vsi, vsi_name, f);\n+\t\t\tif (is_broadcast_ether_addr(new->f->macaddr)) {\n+\t\t\t\tif (i40e_aqc_broadcast_filter(vsi, vsi_name,\n+\t\t\t\t\t\t\t new->f))\n+\t\t\t\t\tnew->state = I40E_FILTER_FAILED;\n+\t\t\t\telse\n+\t\t\t\t\tnew->state = I40E_FILTER_ACTIVE;\n \t\t\t\tcontinue;\n \t\t\t}\n \n \t\t\t/* add to add array */\n \t\t\tif (num_add == 0)\n-\t\t\t\tadd_head = f;\n+\t\t\t\tadd_head = new;\n \t\t\tcmd_flags = 0;\n-\t\t\tether_addr_copy(add_list[num_add].mac_addr, f->macaddr);\n-\t\t\tif (f->vlan == I40E_VLAN_ANY) {\n+\t\t\tether_addr_copy(add_list[num_add].mac_addr,\n+\t\t\t\t\tnew->f->macaddr);\n+\t\t\tif (new->f->vlan == I40E_VLAN_ANY) {\n \t\t\t\tadd_list[num_add].vlan_tag = 0;\n \t\t\t\tcmd_flags |= I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;\n \t\t\t} else {\n \t\t\t\tadd_list[num_add].vlan_tag =\n-\t\t\t\t\tcpu_to_le16((u16)(f->vlan));\n+\t\t\t\t\tcpu_to_le16((u16)(new->f->vlan));\n \t\t\t}\n \t\t\tadd_list[num_add].queue_number = 0;\n \t\t\t/* set invalid match method for later detection */\n@@ -2236,11 +2280,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t * the VSI's list.\n \t\t */\n \t\tspin_lock_bh(&vsi->mac_filter_hash_lock);\n-\t\thlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {\n-\t\t\tu64 key = i40e_addr_to_hkey(f->macaddr);\n-\n-\t\t\thlist_del(&f->hlist);\n-\t\t\thash_add(vsi->mac_filter_hash, &f->hlist, key);\n+\t\thlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {\n+\t\t\t/* Only update the state if we're still NEW */\n+\t\t\tif (new->f->state == I40E_FILTER_NEW)\n+\t\t\t\tnew->f->state = new->state;\n+\t\t\thlist_del(&new->hlist);\n+\t\t\tkfree(new);\n \t\t}\n \t\tspin_unlock_bh(&vsi->mac_filter_hash_lock);\n \t\tkfree(add_list);\n@@ -2389,8 +2434,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t/* Restore elements on the temporary add and delete lists */\n \tspin_lock_bh(&vsi->mac_filter_hash_lock);\n err_no_memory_locked:\n-\ti40e_undo_filter_entries(vsi, &tmp_del_list);\n-\ti40e_undo_filter_entries(vsi, &tmp_add_list);\n+\ti40e_undo_del_filter_entries(vsi, &tmp_del_list);\n+\ti40e_undo_add_filter_entries(vsi, &tmp_add_list);\n \tspin_unlock_bh(&vsi->mac_filter_hash_lock);\n \n \tvsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;\n", "prefixes": [ "next", "S56", "6/8" ] }