Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/514269/?format=api
{ "id": 514269, "url": "http://patchwork.ozlabs.org/api/patches/514269/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1441315142-173025-5-git-send-email-catherine.sullivan@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": "<1441315142-173025-5-git-send-email-catherine.sullivan@intel.com>", "list_archive_url": null, "date": "2015-09-03T21:18:51", "name": "[next,S15,04/15] i40e: Lock for VSI's MAC filter list", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "41ac0c9b5d8a2ae9c97149fb84189cc702fbf3e6", "submitter": { "id": 13931, "url": "http://patchwork.ozlabs.org/api/people/13931/?format=api", "name": "Catherine Sullivan", "email": "catherine.sullivan@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/1441315142-173025-5-git-send-email-catherine.sullivan@intel.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/514269/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/514269/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 hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ozlabs.org (Postfix) with ESMTP id E5F0E140778\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 4 Sep 2015 07:18:44 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 4476D9518C;\n\tThu, 3 Sep 2015 21:18:44 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id qfg0EyL5j6R0; Thu, 3 Sep 2015 21:18:40 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 62A6F952D0;\n\tThu, 3 Sep 2015 21:18:40 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id D2A7E1C1777\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 3 Sep 2015 21:18:38 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id CB9D12757F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 3 Sep 2015 21:18:38 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 9x3OiCsTqFI8 for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 3 Sep 2015 21:18:36 +0000 (UTC)", "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby silver.osuosl.org (Postfix) with ESMTP id 29E2F2E043\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 3 Sep 2015 21:18:36 +0000 (UTC)", "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga103.jf.intel.com with ESMTP; 03 Sep 2015 14:18:16 -0700", "from catheri1-tigger.jf.intel.com ([134.134.176.92])\n\tby orsmga002.jf.intel.com with ESMTP; 03 Sep 2015 14:18:16 -0700" ], "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.17,464,1437462000\"; d=\"scan'208\";a=\"797335983\"", "From": "Catherine Sullivan <catherine.sullivan@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Thu, 3 Sep 2015 17:18:51 -0400", "Message-Id": "<1441315142-173025-5-git-send-email-catherine.sullivan@intel.com>", "X-Mailer": "git-send-email 1.9.3", "In-Reply-To": "<1441315142-173025-1-git-send-email-catherine.sullivan@intel.com>", "References": "<1441315142-173025-1-git-send-email-catherine.sullivan@intel.com>", "Subject": "[Intel-wired-lan] [next PATCH S15 04/15] i40e: Lock for VSI's MAC\n\tfilter list", "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: Kiran Patil <kiran.patil@intel.com>\n\nThis patch introduces a spinlock which is to be used for synchronizing\naccess to VSI's MAC filter list.\n\nThis patch also synchronizes execution of other codepaths which are\naccessing VSI's MAC filter list with execution of\nservice_task:sync_vsi_filters.\n\nIn function i40e_add_vsi, copied out LAA MAC address instead of cloning\nMAC filter entry because only MAC address is needed to remove MAC VLAN\nfilter from FW/HW.\n\nSigned-off-by: Kiran Patil <kiran.patil@intel.com>\nSigned-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>\nChange-ID: I0e10ac7c715d44aa994239642aa4d57c998573a2\n---\n drivers/net/ethernet/intel/i40e/i40e.h | 2 +\n drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 +\n drivers/net/ethernet/intel/i40e/i40e_main.c | 326 +++++++++++++++++----\n drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 +-\n 4 files changed, 300 insertions(+), 56 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 77148f3..a2a1d22 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -469,6 +469,8 @@ struct i40e_vsi {\n #define I40E_VSI_FLAG_VEB_OWNER\t\tBIT(1)\n \tunsigned long flags;\n \n+\t/* Per VSI lock to protect elements/list (MAC filter) */\n+\tspinlock_t mac_filter_list_lock;\n \tstruct list_head mac_filter_list;\n \n \t/* VSI stats */\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c\nindex 2ec2411..61df19e 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c\n@@ -1516,10 +1516,12 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)\n \t * same PCI function.\n \t */\n \tnetdev->dev_port = 1;\n+\tspin_lock(&vsi->mac_filter_list_lock);\n \ti40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);\n \ti40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false);\n \ti40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);\n \ti40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n \t/* use san mac */\n \tether_addr_copy(netdev->dev_addr, hw->mac.san_addr);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 23f36be..a323d6d 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -1212,6 +1212,9 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \tif (!vsi || !macaddr)\n \t\treturn NULL;\n \n@@ -1240,6 +1243,9 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \tif (!vsi || !macaddr)\n \t\treturn NULL;\n \n@@ -1262,6 +1268,9 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \t/* Only -1 for all the filters denotes not in vlan mode\n \t * so we have to go through all the list in order to make sure\n \t */\n@@ -1290,6 +1299,9 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n \t\tif (vsi->info.pvid)\n \t\t\tf->vlan = le16_to_cpu(vsi->info.pvid);\n@@ -1344,6 +1356,10 @@ static int i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)\n * @is_netdev: make sure its a netdev filter, else doesn't matter\n *\n * Returns ptr to the filter object or NULL when no memory available.\n+ *\n+ * NOTE: This function is expected to be called with mac_filter_list_lock\n+ * being held. If needed could add WARN/BUG_ON if lock is not held for debug\n+ * purpose.\n **/\n struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,\n \t\t\t\t\tu8 *macaddr, s16 vlan,\n@@ -1351,6 +1367,9 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \tif (!vsi || !macaddr)\n \t\treturn NULL;\n \n@@ -1402,6 +1421,10 @@ add_filter_out:\n * @vlan: the vlan\n * @is_vf: make sure it's a VF filter, else doesn't matter\n * @is_netdev: make sure it's a netdev filter, else doesn't matter\n+ *\n+ * NOTE: This function is expected to be called with mac_filter_list_lock\n+ * being held. If needed could add WARN/BUG_ON if lock is not held for debug\n+ * purpose.\n **/\n void i40e_del_filter(struct i40e_vsi *vsi,\n \t\t u8 *macaddr, s16 vlan,\n@@ -1409,6 +1432,9 @@ void i40e_del_filter(struct i40e_vsi *vsi,\n {\n \tstruct i40e_mac_filter *f;\n \n+\tWARN(!spin_is_locked(&vsi->mac_filter_list_lock),\n+\t \"Missing mac_filter_list_lock\\n\");\n+\n \tif (!vsi || !macaddr)\n \t\treturn;\n \n@@ -1520,10 +1546,12 @@ static int i40e_set_mac(struct net_device *netdev, void *p)\n \t\telement.flags = cpu_to_le16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);\n \t\ti40e_aq_add_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);\n \t} else {\n+\t\tspin_lock(&vsi->mac_filter_list_lock);\n \t\tf = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,\n \t\t\t\t false, false);\n \t\tif (f)\n \t\t\tf->is_laa = true;\n+\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t}\n \n \ti40e_sync_vsi_filters(vsi);\n@@ -1696,6 +1724,8 @@ static void i40e_set_rx_mode(struct net_device *netdev)\n \tstruct netdev_hw_addr *mca;\n \tstruct netdev_hw_addr *ha;\n \n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\n \t/* add addr if not already in the filter list */\n \tnetdev_for_each_uc_addr(uca, netdev) {\n \t\tif (!i40e_find_mac(vsi, uca->addr, false, true)) {\n@@ -1743,6 +1773,7 @@ static void i40e_set_rx_mode(struct net_device *netdev)\n bottom_of_search_loop:\n \t\tcontinue;\n \t}\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n \t/* check for other flag changes */\n \tif (vsi->current_netdev_flags != vsi->netdev->flags) {\n@@ -1752,6 +1783,79 @@ bottom_of_search_loop:\n }\n \n /**\n+ * i40e_mac_filter_entry_clone - Clones a MAC filter entry\n+ * @src: source MAC filter entry to be clones\n+ *\n+ * Returns the pointer to newly cloned MAC filter entry or NULL\n+ * in case of error\n+ **/\n+static struct i40e_mac_filter *i40e_mac_filter_entry_clone(\n+\t\t\t\t\tstruct i40e_mac_filter *src)\n+{\n+\tstruct i40e_mac_filter *f;\n+\n+\tf = kzalloc(sizeof(*f), GFP_ATOMIC);\n+\tif (!f)\n+\t\treturn NULL;\n+\t*f = *src;\n+\n+\tINIT_LIST_HEAD(&f->list);\n+\n+\treturn f;\n+}\n+\n+/**\n+ * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries\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 removed from device.\n+ **/\n+static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,\n+\t\t\t\t\t struct list_head *from)\n+{\n+\tstruct i40e_mac_filter *f, *ftmp;\n+\n+\tlist_for_each_entry_safe(f, ftmp, from, list) {\n+\t\tf->changed = true;\n+\t\t/* Move the element back into MAC filter list*/\n+\t\tlist_move_tail(&f->list, &vsi->mac_filter_list);\n+\t}\n+}\n+\n+/**\n+ * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries\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 added from device.\n+ **/\n+static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_mac_filter *f, *ftmp;\n+\n+\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n+\t\tif (!f->changed && f->counter)\n+\t\t\tf->changed = true;\n+\t}\n+}\n+\n+/**\n+ * i40e_cleanup_add_list - Deletes the element from add list and release\n+ *\t\t\tmemory\n+ * @from: Pointer to list which contains MAC filter entries\n+ **/\n+static void i40e_cleanup_add_list(struct list_head *add_list)\n+{\n+\tstruct i40e_mac_filter *f, *ftmp;\n+\n+\tlist_for_each_entry_safe(f, ftmp, add_list, list) {\n+\t\tlist_del(&f->list);\n+\t\tkfree(f);\n+\t}\n+}\n+\n+/**\n * i40e_sync_vsi_filters - Update the VSI filter list to the HW\n * @vsi: ptr to the VSI\n *\n@@ -1761,11 +1865,13 @@ bottom_of_search_loop:\n **/\n int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n {\n-\tstruct i40e_mac_filter *f, *ftmp;\n+\tstruct list_head tmp_del_list, tmp_add_list;\n+\tstruct i40e_mac_filter *f, *ftmp, *fclone;\n \tbool promisc_forced_on = false;\n \tbool add_happened = false;\n \tint filter_list_len = 0;\n \tu32 changed_flags = 0;\n+\tbool err_cond = false;\n \ti40e_status ret = 0;\n \tstruct i40e_pf *pf;\n \tint num_add = 0;\n@@ -1786,17 +1892,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\tvsi->current_netdev_flags = vsi->netdev->flags;\n \t}\n \n+\tINIT_LIST_HEAD(&tmp_del_list);\n+\tINIT_LIST_HEAD(&tmp_add_list);\n+\n \tif (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {\n \t\tvsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;\n \n-\t\tfilter_list_len = pf->hw.aq.asq_buf_size /\n-\t\t\t sizeof(struct i40e_aqc_remove_macvlan_element_data);\n-\t\tdel_list = kcalloc(filter_list_len,\n-\t\t\t sizeof(struct i40e_aqc_remove_macvlan_element_data),\n-\t\t\t GFP_KERNEL);\n-\t\tif (!del_list)\n-\t\t\treturn -ENOMEM;\n-\n+\t\tspin_lock(&vsi->mac_filter_list_lock);\n \t\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n \t\t\tif (!f->changed)\n \t\t\t\tcontinue;\n@@ -1804,6 +1906,58 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\tif (f->counter != 0)\n \t\t\t\tcontinue;\n \t\t\tf->changed = false;\n+\n+\t\t\t/* Move the element into temporary del_list */\n+\t\t\tlist_move_tail(&f->list, &tmp_del_list);\n+\t\t}\n+\n+\t\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n+\t\t\tif (!f->changed)\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (f->counter == 0)\n+\t\t\t\tcontinue;\n+\t\t\tf->changed = false;\n+\n+\t\t\t/* Clone MAC filter entry and add into temporary list */\n+\t\t\tfclone = i40e_mac_filter_entry_clone(f);\n+\t\t\tif (!fclone) {\n+\t\t\t\terr_cond = true;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tlist_add_tail(&fclone->list, &tmp_add_list);\n+\t\t}\n+\n+\t\t/* if failed to clone MAC filter entry - undo */\n+\t\tif (err_cond) {\n+\t\t\ti40e_undo_del_filter_entries(vsi, &tmp_del_list);\n+\t\t\ti40e_undo_add_filter_entries(vsi);\n+\t\t}\n+\t\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n+\t\tif (err_cond)\n+\t\t\ti40e_cleanup_add_list(&tmp_add_list);\n+\t}\n+\n+\t/* Now process 'del_list' outside the lock */\n+\tif (!list_empty(&tmp_del_list)) {\n+\t\tfilter_list_len = pf->hw.aq.asq_buf_size /\n+\t\t\t sizeof(struct i40e_aqc_remove_macvlan_element_data);\n+\t\tdel_list = kcalloc(filter_list_len,\n+\t\t\t sizeof(struct i40e_aqc_remove_macvlan_element_data),\n+\t\t\t GFP_KERNEL);\n+\t\tif (!del_list) {\n+\t\t\ti40e_cleanup_add_list(&tmp_add_list);\n+\n+\t\t\t/* Undo VSI's MAC filter entry element updates */\n+\t\t\tspin_lock(&vsi->mac_filter_list_lock);\n+\t\t\ti40e_undo_del_filter_entries(vsi, &tmp_del_list);\n+\t\t\ti40e_undo_add_filter_entries(vsi);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\n+\t\tlist_for_each_entry_safe(f, ftmp, &tmp_del_list, list) {\n \t\t\tcmd_flags = 0;\n \n \t\t\t/* add to delete list */\n@@ -1816,10 +1970,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\tdel_list[num_del].flags = cmd_flags;\n \t\t\tnum_del++;\n \n-\t\t\t/* unlink from filter list */\n-\t\t\tlist_del(&f->list);\n-\t\t\tkfree(f);\n-\n \t\t\t/* flush a full buffer */\n \t\t\tif (num_del == filter_list_len) {\n \t\t\t\tret = i40e_aq_remove_macvlan(&pf->hw,\n@@ -1830,12 +1980,18 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\t\tmemset(del_list, 0, sizeof(*del_list));\n \n \t\t\t\tif (ret && aq_err != I40E_AQ_RC_ENOENT)\n-\t\t\t\t\tdev_info(&pf->pdev->dev,\n-\t\t\t\t\t\t \"ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\\n\",\n-\t\t\t\t\t\t i40e_stat_str(&pf->hw, ret),\n-\t\t\t\t\t\t i40e_aq_str(&pf->hw, aq_err));\n+\t\t\t\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\t\t\t\"ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\\n\",\n+\t\t\t\t\t\ti40e_stat_str(&pf->hw, ret),\n+\t\t\t\t\t\ti40e_aq_str(&pf->hw, aq_err));\n \t\t\t}\n+\t\t\t/* Release memory for MAC filter entries which were\n+\t\t\t * synced up with HW.\n+\t\t\t */\n+\t\t\tlist_del(&f->list);\n+\t\t\tkfree(f);\n \t\t}\n+\n \t\tif (num_del) {\n \t\t\tret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,\n \t\t\t\t\t\t del_list, num_del, NULL);\n@@ -1851,6 +2007,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \n \t\tkfree(del_list);\n \t\tdel_list = NULL;\n+\t}\n+\n+\tif (!list_empty(&tmp_add_list)) {\n \n \t\t/* do all the adds now */\n \t\tfilter_list_len = pf->hw.aq.asq_buf_size /\n@@ -1858,16 +2017,19 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\tadd_list = kcalloc(filter_list_len,\n \t\t\t sizeof(struct i40e_aqc_add_macvlan_element_data),\n \t\t\t GFP_KERNEL);\n-\t\tif (!add_list)\n+\t\tif (!add_list) {\n+\t\t\t/* Purge element from temporary lists */\n+\t\t\ti40e_cleanup_add_list(&tmp_add_list);\n+\n+\t\t\t/* Undo add filter entries from VSI MAC filter list */\n+\t\t\tspin_lock(&vsi->mac_filter_list_lock);\n+\t\t\ti40e_undo_add_filter_entries(vsi);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\treturn -ENOMEM;\n+\t\t}\n \n-\t\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n-\t\t\tif (!f->changed)\n-\t\t\t\tcontinue;\n+\t\tlist_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {\n \n-\t\t\tif (f->counter == 0)\n-\t\t\t\tcontinue;\n-\t\t\tf->changed = false;\n \t\t\tadd_happened = true;\n \t\t\tcmd_flags = 0;\n \n@@ -1894,7 +2056,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\t\t\tbreak;\n \t\t\t\tmemset(add_list, 0, sizeof(*add_list));\n \t\t\t}\n+\t\t\t/* Entries from tmp_add_list were cloned from MAC\n+\t\t\t * filter list, hence clean those cloned entries\n+\t\t\t */\n+\t\t\tlist_del(&f->list);\n+\t\t\tkfree(f);\n \t\t}\n+\n \t\tif (num_add) {\n \t\t\tret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,\n \t\t\t\t\t\t add_list, num_add, NULL);\n@@ -2122,6 +2290,9 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \tis_vf = (vsi->type == I40E_VSI_SRIOV);\n \tis_netdev = !!(vsi->netdev);\n \n+\t/* Locked once because all functions invoked below iterates list*/\n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\n \tif (is_netdev) {\n \t\tadd_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid,\n \t\t\t\t\tis_vf, is_netdev);\n@@ -2129,6 +2300,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\t\tdev_info(&vsi->back->pdev->dev,\n \t\t\t\t \"Could not add vlan filter %d for %pM\\n\",\n \t\t\t\t vid, vsi->netdev->dev_addr);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\treturn -ENOMEM;\n \t\t}\n \t}\n@@ -2139,6 +2311,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\t\tdev_info(&vsi->back->pdev->dev,\n \t\t\t\t \"Could not add vlan filter %d for %pM\\n\",\n \t\t\t\t vid, f->macaddr);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\treturn -ENOMEM;\n \t\t}\n \t}\n@@ -2160,6 +2333,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\t\t\tdev_info(&vsi->back->pdev->dev,\n \t\t\t\t\t \"Could not add filter 0 for %pM\\n\",\n \t\t\t\t\t vsi->netdev->dev_addr);\n+\t\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n@@ -2168,22 +2342,28 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t/* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */\n \tif (vid > 0 && !vsi->info.pvid) {\n \t\tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n-\t\t\tif (i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY,\n-\t\t\t\t\t is_vf, is_netdev)) {\n-\t\t\t\ti40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY,\n-\t\t\t\t\t\tis_vf, is_netdev);\n-\t\t\t\tadd_f = i40e_add_filter(vsi, f->macaddr,\n-\t\t\t\t\t\t\t0, is_vf, is_netdev);\n-\t\t\t\tif (!add_f) {\n-\t\t\t\t\tdev_info(&vsi->back->pdev->dev,\n-\t\t\t\t\t\t \"Could not add filter 0 for %pM\\n\",\n-\t\t\t\t\t\t f->macaddr);\n-\t\t\t\t\treturn -ENOMEM;\n-\t\t\t\t}\n+\t\t\tif (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY,\n+\t\t\t\t\t is_vf, is_netdev))\n+\t\t\t\tcontinue;\n+\t\t\ti40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY,\n+\t\t\t\t\tis_vf, is_netdev);\n+\t\t\tadd_f = i40e_add_filter(vsi, f->macaddr,\n+\t\t\t\t\t\t0, is_vf, is_netdev);\n+\t\t\tif (!add_f) {\n+\t\t\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t\t\t \"Could not add filter 0 for %pM\\n\",\n+\t\t\t\t\tf->macaddr);\n+\t\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n+\t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n \t}\n \n+\t/* Make sure to release before sync_vsi_filter because that\n+\t * function will lock/unlock as necessary\n+\t */\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n \tif (test_bit(__I40E_DOWN, &vsi->back->state) ||\n \t test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))\n \t\treturn 0;\n@@ -2208,6 +2388,9 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n \tis_vf = (vsi->type == I40E_VSI_SRIOV);\n \tis_netdev = !!(netdev);\n \n+\t/* Locked once because all functions invoked below iterates list */\n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\n \tif (is_netdev)\n \t\ti40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev);\n \n@@ -2238,6 +2421,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\t\tdev_info(&vsi->back->pdev->dev,\n \t\t\t\t \"Could not add filter %d for %pM\\n\",\n \t\t\t\t I40E_VLAN_ANY, netdev->dev_addr);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\treturn -ENOMEM;\n \t\t}\n \t}\n@@ -2246,16 +2430,22 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n \t\t\ti40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev);\n \t\t\tadd_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY,\n-\t\t\t\t\t is_vf, is_netdev);\n+\t\t\t\t\t\tis_vf, is_netdev);\n \t\t\tif (!add_f) {\n \t\t\t\tdev_info(&vsi->back->pdev->dev,\n \t\t\t\t\t \"Could not add filter %d for %pM\\n\",\n \t\t\t\t\t I40E_VLAN_ANY, f->macaddr);\n+\t\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n \t}\n \n+\t/* Make sure to release before sync_vsi_filter because that\n+\t * function with lock/unlock as necessary\n+\t */\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n \tif (test_bit(__I40E_DOWN, &vsi->back->state) ||\n \t test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))\n \t\treturn 0;\n@@ -6987,6 +7177,8 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)\n \t/* Setup default MSIX irq handler for VSI */\n \ti40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);\n \n+\t/* Initialize VSI lock */\n+\tspin_lock_init(&vsi->mac_filter_list_lock);\n \tpf->vsi[vsi_idx] = vsi;\n \tret = vsi_idx;\n \tgoto unlock_pf;\n@@ -8510,17 +8702,26 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)\n \t\t * default a MAC-VLAN filter that accepts any tagged packet\n \t\t * which must be replaced by a normal filter.\n \t\t */\n-\t\tif (!i40e_rm_default_mac_filter(vsi, mac_addr))\n+\t\tif (!i40e_rm_default_mac_filter(vsi, mac_addr)) {\n+\t\t\tspin_lock(&vsi->mac_filter_list_lock);\n \t\t\ti40e_add_filter(vsi, mac_addr,\n \t\t\t\t\tI40E_VLAN_ANY, false, true);\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n+\t\t}\n \t} else {\n \t\t/* relate the VSI_VMDQ name to the VSI_MAIN name */\n \t\tsnprintf(netdev->name, IFNAMSIZ, \"%sv%%d\",\n \t\t\t pf->vsi[pf->lan_vsi]->netdev->name);\n \t\trandom_ether_addr(mac_addr);\n+\n+\t\tspin_lock(&vsi->mac_filter_list_lock);\n \t\ti40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false);\n+\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t}\n+\n+\tspin_lock(&vsi->mac_filter_list_lock);\n \ti40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false);\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n \tether_addr_copy(netdev->dev_addr, mac_addr);\n \tether_addr_copy(netdev->perm_addr, mac_addr);\n@@ -8594,10 +8795,13 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi)\n static int i40e_add_vsi(struct i40e_vsi *vsi)\n {\n \tint ret = -ENODEV;\n-\tstruct i40e_mac_filter *f, *ftmp;\n+\tu8 laa_macaddr[ETH_ALEN];\n+\tbool found_laa_mac_filter = false;\n \tstruct i40e_pf *pf = vsi->back;\n \tstruct i40e_hw *hw = &pf->hw;\n \tstruct i40e_vsi_context ctxt;\n+\tstruct i40e_mac_filter *f, *ftmp;\n+\n \tu8 enabled_tc = 0x1; /* TC0 enabled */\n \tint f_count = 0;\n \n@@ -8769,32 +8973,41 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)\n \t\tvsi->id = ctxt.vsi_number;\n \t}\n \n+\tspin_lock(&vsi->mac_filter_list_lock);\n \t/* If macvlan filters already exist, force them to get loaded */\n \tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n \t\tf->changed = true;\n \t\tf_count++;\n \n+\t\t/* Expected to have only one MAC filter entry for LAA in list */\n \t\tif (f->is_laa && vsi->type == I40E_VSI_MAIN) {\n-\t\t\tstruct i40e_aqc_remove_macvlan_element_data element;\n+\t\t\tether_addr_copy(laa_macaddr, f->macaddr);\n+\t\t\tfound_laa_mac_filter = true;\n+\t\t}\n+\t}\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n-\t\t\tmemset(&element, 0, sizeof(element));\n-\t\t\tether_addr_copy(element.mac_addr, f->macaddr);\n-\t\t\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n-\t\t\tret = i40e_aq_remove_macvlan(hw, vsi->seid,\n-\t\t\t\t\t\t &element, 1, NULL);\n-\t\t\tif (ret) {\n-\t\t\t\t/* some older FW has a different default */\n-\t\t\t\telement.flags |=\n-\t\t\t\t\t I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;\n-\t\t\t\ti40e_aq_remove_macvlan(hw, vsi->seid,\n-\t\t\t\t\t\t &element, 1, NULL);\n-\t\t\t}\n+\tif (found_laa_mac_filter) {\n+\t\tstruct i40e_aqc_remove_macvlan_element_data element;\n \n-\t\t\ti40e_aq_mac_address_write(hw,\n-\t\t\t\t\t\t I40E_AQC_WRITE_TYPE_LAA_WOL,\n-\t\t\t\t\t\t f->macaddr, NULL);\n+\t\tmemset(&element, 0, sizeof(element));\n+\t\tether_addr_copy(element.mac_addr, laa_macaddr);\n+\t\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n+\t\tret = i40e_aq_remove_macvlan(hw, vsi->seid,\n+\t\t\t\t\t &element, 1, NULL);\n+\t\tif (ret) {\n+\t\t\t/* some older FW has a different default */\n+\t\t\telement.flags |=\n+\t\t\t\t I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;\n+\t\t\ti40e_aq_remove_macvlan(hw, vsi->seid,\n+\t\t\t\t\t &element, 1, NULL);\n \t\t}\n+\n+\t\ti40e_aq_mac_address_write(hw,\n+\t\t\t\t\t I40E_AQC_WRITE_TYPE_LAA_WOL,\n+\t\t\t\t\t laa_macaddr, NULL);\n \t}\n+\n \tif (f_count) {\n \t\tvsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;\n \t\tpf->flags |= I40E_FLAG_FILTER_SYNC;\n@@ -8857,9 +9070,12 @@ int i40e_vsi_release(struct i40e_vsi *vsi)\n \t\ti40e_vsi_disable_irq(vsi);\n \t}\n \n+\tspin_lock(&vsi->mac_filter_list_lock);\n \tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)\n \t\ti40e_del_filter(vsi, f->macaddr, f->vlan,\n \t\t\t\tf->is_vf, f->is_netdev);\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n \ti40e_sync_vsi_filters(vsi);\n \n \ti40e_vsi_delete(vsi);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\nindex 17c21b9..4e383f9 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n@@ -547,6 +547,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)\n \t\t */\n \t\tif (vf->port_vlan_id)\n \t\t\ti40e_vsi_add_pvid(vsi, vf->port_vlan_id);\n+\n+\t\tspin_lock(&vsi->mac_filter_list_lock);\n \t\tf = i40e_add_filter(vsi, vf->default_lan_addr.addr,\n \t\t\t\t vf->port_vlan_id ? vf->port_vlan_id : -1,\n \t\t\t\t true, false);\n@@ -559,6 +561,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)\n \t\tif (!f)\n \t\t\tdev_info(&pf->pdev->dev,\n \t\t\t\t \"Could not allocate VF broadcast filter\\n\");\n+\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t}\n \n \t/* program mac filter */\n@@ -1592,6 +1595,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)\n \t}\n \tvsi = pf->vsi[vf->lan_vsi_idx];\n \n+\t/* Lock once, because all function inside for loop accesses VSI's\n+\t * MAC filter list which needs to be protected using same lock.\n+\t */\n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\n \t/* add new addresses to the list */\n \tfor (i = 0; i < al->num_elements; i++) {\n \t\tstruct i40e_mac_filter *f;\n@@ -1610,9 +1618,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)\n \t\t\tdev_err(&pf->pdev->dev,\n \t\t\t\t\"Unable to add VF MAC filter\\n\");\n \t\t\tret = I40E_ERR_PARAM;\n+\t\t\tspin_unlock(&vsi->mac_filter_list_lock);\n \t\t\tgoto error_param;\n \t\t}\n \t}\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n \t/* program the updated filter list */\n \tif (i40e_sync_vsi_filters(vsi))\n@@ -1660,10 +1670,12 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)\n \t}\n \tvsi = pf->vsi[vf->lan_vsi_idx];\n \n+\tspin_lock(&vsi->mac_filter_list_lock);\n \t/* delete addresses from the list */\n \tfor (i = 0; i < al->num_elements; i++)\n \t\ti40e_del_filter(vsi, al->list[i].addr,\n \t\t\t\tI40E_VLAN_ANY, true, false);\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n \n \t/* program the updated filter list */\n \tif (i40e_sync_vsi_filters(vsi))\n@@ -2060,6 +2072,11 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)\n \t\tgoto error_param;\n \t}\n \n+\t/* Lock once because below invoked function add/del_filter requires\n+\t * mac_filter_list_lock to be held\n+\t */\n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\n \t/* delete the temporary mac address */\n \ti40e_del_filter(vsi, vf->default_lan_addr.addr,\n \t\t\tvf->port_vlan_id ? vf->port_vlan_id : -1,\n@@ -2071,6 +2088,8 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)\n \tlist_for_each_entry(f, &vsi->mac_filter_list, list)\n \t\ti40e_del_filter(vsi, f->macaddr, f->vlan, true, false);\n \n+\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n \tdev_info(&pf->pdev->dev, \"Setting MAC %pM on VF %d\\n\", mac, vf_id);\n \t/* program mac filter */\n \tif (i40e_sync_vsi_filters(vsi)) {\n@@ -2103,6 +2122,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,\n \tu16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT);\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n \tstruct i40e_pf *pf = np->vsi->back;\n+\tbool is_vsi_in_vlan = false;\n \tstruct i40e_vsi *vsi;\n \tstruct i40e_vf *vf;\n \tint ret = 0;\n@@ -2132,7 +2152,11 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,\n \t\t/* duplicate request, so just return success */\n \t\tgoto error_pvid;\n \n-\tif (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {\n+\tspin_lock(&vsi->mac_filter_list_lock);\n+\tis_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi);\n+\tspin_unlock(&vsi->mac_filter_list_lock);\n+\n+\tif (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) {\n \t\tdev_err(&pf->pdev->dev,\n \t\t\t\"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\\nPlease unload and reload the VF driver for this change to take effect.\\n\",\n \t\t\tvf_id);\n", "prefixes": [ "next", "S15", "04/15" ] }