get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/638103/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 638103,
    "url": "http://patchwork.ozlabs.org/api/patches/638103/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1466439039-16378-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": "<1466439039-16378-7-git-send-email-bimmy.pujari@intel.com>",
    "list_archive_url": null,
    "date": "2016-06-20T16:10:38",
    "name": "[next,PTACH,S38-v2,6/7] i40e: refactor rx filter handling",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "e441986f3d4459d6d49b9ae28c01aa2e61d1ecff",
    "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/1466439039-16378-7-git-send-email-bimmy.pujari@intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/638103/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/638103/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 3rYG6Y4KMpz9s9r\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 21 Jun 2016 02:10:29 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id E64BE888F7;\n\tMon, 20 Jun 2016 16:10:27 +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 jde2FfvYUJef; Mon, 20 Jun 2016 16:10:19 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 5D92E88868;\n\tMon, 20 Jun 2016 16:10:16 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 81FFA1C09EB\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Jun 2016 16:10:11 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 3400F8AF69\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Jun 2016 16:10:11 +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 2kyUr2ouuG3V for <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Jun 2016 16:10:08 +0000 (UTC)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id CC92B938E4\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Jun 2016 16:10:08 +0000 (UTC)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga101.fm.intel.com with ESMTP; 20 Jun 2016 09:10:08 -0700",
            "from bimmy.jf.intel.com (HELO bimmy.linux1.jf.intel.com)\n\t([134.134.2.177])\n\tby fmsmga001.fm.intel.com with ESMTP; 20 Jun 2016 09:10:08 -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.26,499,1459839600\"; d=\"scan'208\";a=\"991493115\"",
        "From": "Bimmy Pujari <bimmy.pujari@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Mon, 20 Jun 2016 09:10:38 -0700",
        "Message-Id": "<1466439039-16378-7-git-send-email-bimmy.pujari@intel.com>",
        "X-Mailer": "git-send-email 2.4.11",
        "In-Reply-To": "<1466439039-16378-1-git-send-email-bimmy.pujari@intel.com>",
        "References": "<1466439039-16378-1-git-send-email-bimmy.pujari@intel.com>",
        "Subject": "[Intel-wired-lan] [next PTACH S38-v2 6/7] i40e: refactor rx filter\n\thandling",
        "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: Mitch Williams <mitch.a.williams@intel.com>\n\nProperly track filter adds and deletes so the driver doesn't lose filters\nduring resets and up/down cycles. Add a tracking mechanism so that the\ndriver knows when to enter and leave promiscuous mode.\n\nImplement a simple state machine so the driver can track the status of\neach filter throughout its lifecycle. Properly manage the overflow promiscuous\nstate for the each VSI, and provide a way for the driver to detect when to exit\noverflow promiscuous mode.\n\nRemove all possible default MAC filters that the firmware may have set up so\nthat the driver can manage these correctly, particularly when VLANs come into\nplay. Remove the LAA flag for filters; instead just send whatever we get through\nset_mac to the firmware as the LAA for wakeup purposes.\n\nFinally, add the state of each filter to debugfs output so we can see what's\ngoing on inside the driver's pointy little head.\n\nSigned-off-by: Mitch Williams <mitch.a.williams@intel.com>\nChange-ID: I97c5e366fac2254fa01eaff4f65c0af61dcf2e1f\n---\nTesting Hints : Add many filters (at least 2000). See the device go into\npromiscuous mode. Remove all of these filters and watch the device come back\nfrom promiscuous mode. Do resets during all stages of this process and make\nsure the filter state is consistent throughout using debugfs.\n\n drivers/net/ethernet/intel/i40e/i40e.h         |  14 +-\n drivers/net/ethernet/intel/i40e/i40e_debugfs.c |  16 +-\n drivers/net/ethernet/intel/i40e/i40e_main.c    | 512 ++++++++++++-------------\n 3 files changed, 262 insertions(+), 280 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex e83fc8a..2a88291 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -448,6 +448,14 @@ struct i40e_pf {\n \tu16 phy_led_val;\n };\n \n+enum i40e_filter_state {\n+\tI40E_FILTER_INVALID = 0,\t/* Invalid state */\n+\tI40E_FILTER_NEW,\t\t/* New, not sent to FW yet */\n+\tI40E_FILTER_ACTIVE,\t\t/* Added to switch by FW */\n+\tI40E_FILTER_FAILED,\t\t/* Rejected by FW */\n+\tI40E_FILTER_REMOVE,\t\t/* To be removed */\n+/* There is no 'removed' state; the filter struct is freed */\n+};\n struct i40e_mac_filter {\n \tstruct list_head list;\n \tu8 macaddr[ETH_ALEN];\n@@ -456,8 +464,7 @@ struct i40e_mac_filter {\n \tu8 counter;\t\t/* number of instances of this filter */\n \tbool is_vf;\t\t/* filter belongs to a VF */\n \tbool is_netdev;\t\t/* filter belongs to a netdev */\n-\tbool changed;\t\t/* filter needs to be sync'd to the HW */\n-\tbool is_laa;\t\t/* filter is a Locally Administered Address */\n+\tenum i40e_filter_state state;\n };\n \n struct i40e_veb {\n@@ -523,6 +530,9 @@ struct i40e_vsi {\n \tstruct i40e_ring **rx_rings;\n \tstruct i40e_ring **tx_rings;\n \n+\tu32  active_filters;\n+\tu32  promisc_threshold;\n+\n \tu16 work_limit;\n \tu16 int_rate_limit;  /* value in usecs */\n \ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c\nindex e6af8c8..05cf9a7 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c\n@@ -116,6 +116,14 @@ static ssize_t i40e_dbg_command_read(struct file *filp, char __user *buffer,\n \treturn len;\n }\n \n+static char *i40e_filter_state_string[] = {\n+\t\"INVALID\",\n+\t\"NEW\",\n+\t\"ACTIVE\",\n+\t\"FAILED\",\n+\t\"REMOVE\",\n+};\n+\n /**\n  * i40e_dbg_dump_vsi_seid - handles dump vsi seid write into command datum\n  * @pf: the i40e_pf created in command write\n@@ -160,10 +168,14 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)\n \t\t\t pf->hw.mac.port_addr);\n \tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n \t\tdev_info(&pf->pdev->dev,\n-\t\t\t \"    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d\\n\",\n+\t\t\t \"    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\\n\",\n \t\t\t f->macaddr, f->vlan, f->is_netdev, f->is_vf,\n-\t\t\t f->counter);\n+\t\t\t f->counter, i40e_filter_state_string[f->state]);\n \t}\n+\tdev_info(&pf->pdev->dev, \"    active_filters %d, promisc_threshold %d, overflow promisc %s\\n\",\n+\t\t vsi->active_filters, vsi->promisc_threshold,\n+\t\t (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?\n+\t\t  \"ON\" : \"OFF\"));\n \tnstat = i40e_get_vsi_stats_struct(vsi);\n \tdev_info(&pf->pdev->dev,\n \t\t \"    net_stats: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\\n\",\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 0898c9d..6ae0c56 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -1279,8 +1279,9 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,\n \t\t    (is_vf == f->is_vf) &&\n \t\t    (is_netdev == f->is_netdev)) {\n \t\t\tf->counter--;\n-\t\t\tf->changed = true;\n \t\t\tchanged = 1;\n+\t\t\tif (f->counter == 0)\n+\t\t\t\tf->state = I40E_FILTER_REMOVE;\n \t\t}\n \t}\n \tif (changed) {\n@@ -1296,29 +1297,32 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,\n  * @vsi: the PF Main VSI - inappropriate for any other VSI\n  * @macaddr: the MAC address\n  *\n- * Some older firmware configurations set up a default promiscuous VLAN\n- * filter that needs to be removed.\n+ * Remove whatever filter the firmware set up so the driver can manage\n+ * its own filtering intelligently.\n  **/\n-static int i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)\n+static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)\n {\n \tstruct i40e_aqc_remove_macvlan_element_data element;\n \tstruct i40e_pf *pf = vsi->back;\n-\ti40e_status ret;\n \n \t/* Only appropriate for the PF main VSI */\n \tif (vsi->type != I40E_VSI_MAIN)\n-\t\treturn -EINVAL;\n+\t\treturn;\n \n \tmemset(&element, 0, sizeof(element));\n \tether_addr_copy(element.mac_addr, macaddr);\n \telement.vlan_tag = 0;\n-\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |\n-\t\t\tI40E_AQC_MACVLAN_DEL_IGNORE_VLAN;\n-\tret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);\n-\tif (ret)\n-\t\treturn -ENOENT;\n+\t/* Ignore error returns, some firmware does it this way... */\n+\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n+\ti40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);\n \n-\treturn 0;\n+\tmemset(&element, 0, sizeof(element));\n+\tether_addr_copy(element.mac_addr, macaddr);\n+\telement.vlan_tag = 0;\n+\t/* ...and some firmware does it this way. */\n+\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |\n+\t\t\tI40E_AQC_MACVLAN_ADD_IGNORE_VLAN;\n+\ti40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);\n }\n \n /**\n@@ -1339,6 +1343,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,\n \t\t\t\t\tbool is_vf, bool is_netdev)\n {\n \tstruct i40e_mac_filter *f;\n+\tint changed = false;\n \n \tif (!vsi || !macaddr)\n \t\treturn NULL;\n@@ -1358,8 +1363,15 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,\n \n \t\tether_addr_copy(f->macaddr, macaddr);\n \t\tf->vlan = vlan;\n-\t\tf->changed = true;\n-\n+\t\t/* If we're in overflow promisc mode, set the state directly\n+\t\t * to failed, so we don't bother to try sending the filter\n+\t\t * to the hardware.\n+\t\t */\n+\t\tif (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))\n+\t\t\tf->state = I40E_FILTER_FAILED;\n+\t\telse\n+\t\t\tf->state = I40E_FILTER_NEW;\n+\t\tchanged = true;\n \t\tINIT_LIST_HEAD(&f->list);\n \t\tlist_add_tail(&f->list, &vsi->mac_filter_list);\n \t}\n@@ -1379,10 +1391,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,\n \t\tf->counter++;\n \t}\n \n-\t/* changed tells sync_filters_subtask to\n-\t * push the filter down to the firmware\n-\t */\n-\tif (f->changed) {\n+\tif (changed) {\n \t\tvsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;\n \t\tvsi->back->flags |= I40E_FLAG_FILTER_SYNC;\n \t}\n@@ -1401,6 +1410,9 @@ add_filter_out:\n  *\n  * NOTE: This function is expected to be called with mac_filter_list_lock\n  * being held.\n+ * ANOTHER NOTE: This function MUST be called from within the context of\n+ * the \"safe\" variants of any list iterators, e.g. list_for_each_entry_safe()\n+ * instead of list_for_each_entry().\n  **/\n void i40e_del_filter(struct i40e_vsi *vsi,\n \t\t     u8 *macaddr, s16 vlan,\n@@ -1440,9 +1452,18 @@ void i40e_del_filter(struct i40e_vsi *vsi,\n \t * remove the filter from the firmware's list\n \t */\n \tif (f->counter == 0) {\n-\t\tf->changed = true;\n-\t\tvsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;\n-\t\tvsi->back->flags |= I40E_FLAG_FILTER_SYNC;\n+\t\tif ((f->state == I40E_FILTER_FAILED) ||\n+\t\t    (f->state == I40E_FILTER_NEW)) {\n+\t\t\t/* this one never got added by the FW. Just remove it,\n+\t\t\t * no need to sync anything.\n+\t\t\t */\n+\t\t\tlist_del(&f->list);\n+\t\t\tkfree(f);\n+\t\t} else {\n+\t\t\tf->state = I40E_FILTER_REMOVE;\n+\t\t\tvsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;\n+\t\t\tvsi->back->flags |= I40E_FLAG_FILTER_SYNC;\n+\t\t}\n \t}\n }\n \n@@ -1464,7 +1485,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)\n \tstruct i40e_pf *pf = vsi->back;\n \tstruct i40e_hw *hw = &pf->hw;\n \tstruct sockaddr *addr = p;\n-\tstruct i40e_mac_filter *f;\n \n \tif (!is_valid_ether_addr(addr->sa_data))\n \t\treturn -EADDRNOTAVAIL;\n@@ -1485,52 +1505,23 @@ static int i40e_set_mac(struct net_device *netdev, void *p)\n \telse\n \t\tnetdev_info(netdev, \"set new mac address %pM\\n\", addr->sa_data);\n \n+\tspin_lock_bh(&vsi->mac_filter_list_lock);\n+\ti40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true);\n+\ti40e_put_mac_in_vlan(vsi, addr->sa_data, false, true);\n+\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n+\tether_addr_copy(netdev->dev_addr, addr->sa_data);\n \tif (vsi->type == I40E_VSI_MAIN) {\n \t\ti40e_status ret;\n \n \t\tret = i40e_aq_mac_address_write(&vsi->back->hw,\n \t\t\t\t\t\tI40E_AQC_WRITE_TYPE_LAA_WOL,\n \t\t\t\t\t\taddr->sa_data, NULL);\n-\t\tif (ret) {\n-\t\t\tnetdev_info(netdev,\n-\t\t\t\t    \"Addr change for Main VSI failed: %d\\n\",\n-\t\t\t\t    ret);\n-\t\t\treturn -EADDRNOTAVAIL;\n-\t\t}\n-\t}\n-\n-\tif (ether_addr_equal(netdev->dev_addr, hw->mac.addr)) {\n-\t\tstruct i40e_aqc_remove_macvlan_element_data element;\n-\n-\t\tmemset(&element, 0, sizeof(element));\n-\t\tether_addr_copy(element.mac_addr, netdev->dev_addr);\n-\t\telement.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n-\t\ti40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);\n-\t} else {\n-\t\tspin_lock_bh(&vsi->mac_filter_list_lock);\n-\t\ti40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,\n-\t\t\t\tfalse, false);\n-\t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n-\t}\n-\n-\tif (ether_addr_equal(addr->sa_data, hw->mac.addr)) {\n-\t\tstruct i40e_aqc_add_macvlan_element_data element;\n-\n-\t\tmemset(&element, 0, sizeof(element));\n-\t\tether_addr_copy(element.mac_addr, hw->mac.addr);\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_bh(&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_bh(&vsi->mac_filter_list_lock);\n+\t\tif (ret)\n+\t\t\tnetdev_info(netdev, \"Ignoring error from firmware on LAA update, status %s, AQ ret %s\\n\",\n+\t\t\t\t    i40e_stat_str(hw, ret),\n+\t\t\t\t    i40e_aq_str(hw, hw->aq.asq_last_status));\n \t}\n \n-\tether_addr_copy(netdev->dev_addr, addr->sa_data);\n-\n \t/* schedule our worker thread which will take care of\n \t * applying the new filter changes\n \t */\n@@ -1761,28 +1752,6 @@ 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  * @vsi: pointer to vsi struct\n  * @from: Pointer to list which contains MAC filter entries - changes to\n@@ -1796,41 +1765,61 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,\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- * @vsi: pointer to vsi struct\n+ * i40e_update_filter_state - Update filter state based on return data\n+ * from firmware\n+ * @count: Number of filters added\n+ * @add_list: return data from fw\n+ * @head: pointer to first filter in current batch\n+ * @aq_err: status from fw\n  *\n- * MAC filter entries from list were slated to be added from device.\n+ * MAC filter entries from list were slated to be added to device. Returns\n+ * number of successful filters. Note that 0 does NOT mean success!\n  **/\n-static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi)\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, int aq_err)\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+\tint retval = 0;\n+\tint i;\n \n-/**\n- * i40e_cleanup_add_list - Deletes the element from add list and release\n- *\t\t\tmemory\n- * @add_list: 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+\tif (!aq_err) {\n+\t\tretval = count;\n+\t\t/* Everything's good, mark all filters active. */\n+\t\tfor (i = 0; i < count ; i++) {\n+\t\t\tadd_head->state = I40E_FILTER_ACTIVE;\n+\t\t\tadd_head = list_next_entry(add_head, list);\n+\t\t}\n+\t} else if (aq_err == I40E_AQ_RC_ENOSPC) {\n+\t\t/* Device ran out of filter space. Check the return value\n+\t\t * for each filter to see which ones are active.\n+\t\t */\n+\t\tfor (i = 0; i < count ; i++) {\n+\t\t\tif (add_list[i].match_method ==\n+\t\t\t    I40E_AQC_MM_ERR_NO_RES) {\n+\t\t\t\tadd_head->state = I40E_FILTER_FAILED;\n+\t\t\t} else {\n+\t\t\t\tadd_head->state = I40E_FILTER_ACTIVE;\n+\t\t\t\tretval++;\n+\t\t\t}\n+\t\t\tadd_head = list_next_entry(add_head, list);\n+\t\t}\n+\t} else {\n+\t\t/* Some other horrible thing happened, fail all filters */\n+\t\tretval = 0;\n+\t\tfor (i = 0; i < count ; i++) {\n+\t\t\tadd_head->state = I40E_FILTER_FAILED;\n+\t\t\tadd_head = list_next_entry(add_head, list);\n+\t\t}\n \t}\n+\treturn retval;\n }\n \n /**\n@@ -1843,22 +1832,22 @@ static void i40e_cleanup_add_list(struct list_head *add_list)\n  **/\n int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n {\n-\tstruct list_head tmp_del_list, tmp_add_list;\n-\tstruct i40e_mac_filter *f, *ftmp, *fclone;\n+\tstruct i40e_mac_filter *f, *ftmp, *add_head = NULL;\n+\tstruct list_head tmp_add_list, tmp_del_list;\n \tstruct i40e_hw *hw = &vsi->back->hw;\n-\tbool promisc_forced_on = false;\n-\tbool add_happened = false;\n+\tbool promisc_changed = false;\n \tchar vsi_name[16] = \"PF\";\n \tint filter_list_len = 0;\n \tu32 changed_flags = 0;\n \ti40e_status aq_ret = 0;\n-\tbool err_cond = false;\n \tint retval = 0;\n \tstruct i40e_pf *pf;\n \tint num_add = 0;\n \tint num_del = 0;\n \tint aq_err = 0;\n \tu16 cmd_flags;\n+\tint list_size;\n+\tint fcnt;\n \n \t/* empty array typed pointers, kcalloc later */\n \tstruct i40e_aqc_add_macvlan_element_data *add_list;\n@@ -1873,8 +1862,8 @@ 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+\tINIT_LIST_HEAD(&tmp_del_list);\n \n \tif (vsi->type == I40E_VSI_SRIOV)\n \t\tsnprintf(vsi_name, sizeof(vsi_name) - 1, \"VF %d\", vsi->vf_id);\n@@ -1885,65 +1874,34 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\tvsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;\n \n \t\tspin_lock_bh(&vsi->mac_filter_list_lock);\n+\t\t/* Create a list of filters to delete. */\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/* 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\tif (f->state == I40E_FILTER_REMOVE) {\n+\t\t\t\tWARN_ON(f->counter != 0);\n+\t\t\t\t/* Move the element into temporary del_list */\n+\t\t\t\tlist_move_tail(&f->list, &tmp_del_list);\n+\t\t\t\tvsi->active_filters--;\n+\t\t\t}\n+\t\t\tif (f->state == I40E_FILTER_NEW) {\n+\t\t\t\tWARN_ON(f->counter == 0);\n+\t\t\t\t/* Move the element into temporary add_list */\n+\t\t\t\tlist_move_tail(&f->list, &tmp_add_list);\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_bh(&vsi->mac_filter_list_lock);\n-\n-\t\tif (err_cond) {\n-\t\t\ti40e_cleanup_add_list(&tmp_add_list);\n-\t\t\tretval = -ENOMEM;\n-\t\t\tgoto out;\n-\t\t}\n \t}\n \n \t/* Now process 'del_list' outside the lock */\n \tif (!list_empty(&tmp_del_list)) {\n-\t\tint del_list_size;\n-\n \t\tfilter_list_len = hw->aq.asq_buf_size /\n \t\t\t    sizeof(struct i40e_aqc_remove_macvlan_element_data);\n-\t\tdel_list_size = filter_list_len *\n+\t\tlist_size = filter_list_len *\n \t\t\t    sizeof(struct i40e_aqc_remove_macvlan_element_data);\n-\t\tdel_list = kzalloc(del_list_size, GFP_ATOMIC);\n+\t\tdel_list = kzalloc(list_size, GFP_ATOMIC);\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_bh(&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_bh(&vsi->mac_filter_list_lock);\n \t\t\tretval = -ENOMEM;\n \t\t\tgoto out;\n@@ -1954,9 +1912,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \n \t\t\t/* add to delete list */\n \t\t\tether_addr_copy(del_list[num_del].mac_addr, f->macaddr);\n-\t\t\tdel_list[num_del].vlan_tag =\n-\t\t\t\tcpu_to_le16((u16)(f->vlan ==\n-\t\t\t\t\t    I40E_VLAN_ANY ? 0 : f->vlan));\n+\t\t\tif (f->vlan == I40E_VLAN_ANY) {\n+\t\t\t\tdel_list[num_del].vlan_tag = 0;\n+\t\t\t\tcmd_flags |= I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;\n+\t\t\t} else {\n+\t\t\t\tdel_list[num_del].vlan_tag =\n+\t\t\t\t\tcpu_to_le16((u16)(f->vlan));\n+\t\t\t}\n \n \t\t\tcmd_flags |= I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n \t\t\tdel_list[num_del].flags = cmd_flags;\n@@ -1964,18 +1926,20 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \n \t\t\t/* flush a full buffer */\n \t\t\tif (num_del == filter_list_len) {\n-\t\t\t\taq_ret =\n-\t\t\t\t\ti40e_aq_remove_macvlan(hw, vsi->seid,\n-\t\t\t\t\t\t\t       del_list,\n-\t\t\t\t\t\t\t       num_del, NULL);\n+\t\t\t\taq_ret = i40e_aq_remove_macvlan(hw, vsi->seid,\n+\t\t\t\t\t\t\t\tdel_list,\n+\t\t\t\t\t\t\t\tnum_del, NULL);\n \t\t\t\taq_err = hw->aq.asq_last_status;\n \t\t\t\tnum_del = 0;\n-\t\t\t\tmemset(del_list, 0, del_list_size);\n+\t\t\t\tmemset(del_list, 0, list_size);\n \n-\t\t\t\tif (aq_ret && aq_err != I40E_AQ_RC_ENOENT) {\n+\t\t\t\t/* Explicitly ignore and do not report when\n+\t\t\t\t * firmware returns ENOENT.\n+\t\t\t\t */\n+\t\t\t\tif (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {\n \t\t\t\t\tretval = -EIO;\n-\t\t\t\t\tdev_err(&pf->pdev->dev,\n-\t\t\t\t\t\t \"ignoring delete macvlan error on %s, err %s, aq_err %s while flushing a full buffer\\n\",\n+\t\t\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t\t\t \"ignoring delete macvlan error on %s, err %s, aq_err %s\\n\",\n \t\t\t\t\t\t vsi_name,\n \t\t\t\t\t\t i40e_stat_str(hw, aq_ret),\n \t\t\t\t\t\t i40e_aq_str(hw, aq_err));\n@@ -1994,12 +1958,17 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\taq_err = hw->aq.asq_last_status;\n \t\t\tnum_del = 0;\n \n-\t\t\tif (aq_ret && aq_err != I40E_AQ_RC_ENOENT)\n+\t\t\t/* Explicitly ignore and do not report when firmware\n+\t\t\t * returns ENOENT.\n+\t\t\t */\n+\t\t\tif (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {\n+\t\t\t\tretval = -EIO;\n \t\t\t\tdev_info(&pf->pdev->dev,\n \t\t\t\t\t \"ignoring delete macvlan error on %s, err %s aq_err %s\\n\",\n \t\t\t\t\t vsi_name,\n \t\t\t\t\t i40e_stat_str(hw, aq_ret),\n \t\t\t\t\t i40e_aq_str(hw, aq_err));\n+\t\t\t}\n \t\t}\n \n \t\tkfree(del_list);\n@@ -2007,38 +1976,36 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t}\n \n \tif (!list_empty(&tmp_add_list)) {\n-\t\tint add_list_size;\n-\n-\t\t/* do all the adds now */\n+\t\t/* Do all the adds now. */\n \t\tfilter_list_len = hw->aq.asq_buf_size /\n-\t\t\t       sizeof(struct i40e_aqc_add_macvlan_element_data),\n-\t\tadd_list_size = filter_list_len *\n \t\t\t       sizeof(struct i40e_aqc_add_macvlan_element_data);\n-\t\tadd_list = kzalloc(add_list_size, GFP_ATOMIC);\n+\t\tlist_size = filter_list_len *\n+\t\t\t       sizeof(struct i40e_aqc_add_macvlan_element_data);\n+\t\tadd_list = kzalloc(list_size, GFP_ATOMIC);\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_bh(&vsi->mac_filter_list_lock);\n-\t\t\ti40e_undo_add_filter_entries(vsi);\n-\t\t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n \t\t\tretval = -ENOMEM;\n \t\t\tgoto out;\n \t\t}\n-\n-\t\tlist_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {\n-\n-\t\t\tadd_happened = true;\n-\t\t\tcmd_flags = 0;\n-\n+\t\tnum_add = 0;\n+\t\tlist_for_each_entry(f, &tmp_add_list, list) {\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\tcontinue;\n+\t\t\t}\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\tcmd_flags = 0;\n \t\t\tether_addr_copy(add_list[num_add].mac_addr, f->macaddr);\n-\t\t\tadd_list[num_add].vlan_tag =\n-\t\t\t\tcpu_to_le16(\n-\t\t\t\t (u16)(f->vlan == I40E_VLAN_ANY ? 0 : f->vlan));\n+\t\t\tif (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}\n \t\t\tadd_list[num_add].queue_number = 0;\n-\n \t\t\tcmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;\n \t\t\tadd_list[num_add].flags = cpu_to_le16(cmd_flags);\n \t\t\tnum_add++;\n@@ -2049,44 +2016,77 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\t\t\t\t\t     add_list, num_add,\n \t\t\t\t\t\t\t     NULL);\n \t\t\t\taq_err = hw->aq.asq_last_status;\n+\t\t\t\tfcnt = i40e_update_filter_state(num_add,\n+\t\t\t\t\t\t\t\tadd_list,\n+\t\t\t\t\t\t\t\tadd_head,\n+\t\t\t\t\t\t\t\taq_ret);\n+\t\t\t\tvsi->active_filters += fcnt;\n+\n+\t\t\t\tif (fcnt != num_add) {\n+\t\t\t\t\tpromisc_changed = true;\n+\t\t\t\t\tset_bit(__I40E_FILTER_OVERFLOW_PROMISC,\n+\t\t\t\t\t\t&vsi->state);\n+\t\t\t\t\tvsi->promisc_threshold =\n+\t\t\t\t\t\t(vsi->active_filters * 3) / 4;\n+\t\t\t\t\tdev_warn(&pf->pdev->dev,\n+\t\t\t\t\t\t \"Error %s adding RX filters on %s, promiscuous mode forced on\\n\",\n+\t\t\t\t\t\t i40e_aq_str(hw, aq_err),\n+\t\t\t\t\t\t vsi_name);\n+\t\t\t\t}\n+\t\t\t\tmemset(add_list, 0, list_size);\n \t\t\t\tnum_add = 0;\n-\n-\t\t\t\tif (aq_ret)\n-\t\t\t\t\tbreak;\n-\t\t\t\tmemset(add_list, 0, add_list_size);\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\taq_ret = i40e_aq_add_macvlan(hw, vsi->seid,\n \t\t\t\t\t\t     add_list, num_add, NULL);\n \t\t\taq_err = hw->aq.asq_last_status;\n-\t\t\tnum_add = 0;\n+\t\t\tfcnt = i40e_update_filter_state(num_add, add_list,\n+\t\t\t\t\t\t\tadd_head, aq_ret);\n+\t\t\tvsi->active_filters += fcnt;\n+\t\t\tif (fcnt != num_add) {\n+\t\t\t\tpromisc_changed = true;\n+\t\t\t\tset_bit(__I40E_FILTER_OVERFLOW_PROMISC,\n+\t\t\t\t\t&vsi->state);\n+\t\t\t\tvsi->promisc_threshold =\n+\t\t\t\t\t\t(vsi->active_filters * 3) / 4;\n+\t\t\t\tdev_warn(&pf->pdev->dev,\n+\t\t\t\t\t \"Error %s adding RX filters on %s, promiscuous mode forced on\\n\",\n+\t\t\t\t\t i40e_aq_str(hw, aq_err), vsi_name);\n+\t\t\t}\n \t\t}\n+\t\t/* Now move all of the filters from the temp add list back to\n+\t\t * the VSI's list.\n+\t\t */\n+\t\tspin_lock_bh(&vsi->mac_filter_list_lock);\n+\t\tlist_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {\n+\t\t\tlist_move_tail(&f->list, &vsi->mac_filter_list);\n+\t\t}\n+\t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n \t\tkfree(add_list);\n \t\tadd_list = NULL;\n+\t}\n \n-\t\tif (add_happened && aq_ret && aq_err != I40E_AQ_RC_EINVAL) {\n-\t\t\tretval = i40e_aq_rc_to_posix(aq_ret, aq_err);\n+\t/* Check to see if we can drop out of overflow promiscuous mode. */\n+\tif (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&\n+\t    (vsi->active_filters < vsi->promisc_threshold)) {\n+\t\tint failed_count = 0;\n+\t\t/* See if we have any failed filters. We can't drop out of\n+\t\t * promiscuous until these have all been deleted.\n+\t\t */\n+\t\tspin_lock_bh(&vsi->mac_filter_list_lock);\n+\t\tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n+\t\t\tif (f->state == I40E_FILTER_FAILED)\n+\t\t\t\tfailed_count++;\n+\t\t}\n+\t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n+\t\tif (!failed_count) {\n \t\t\tdev_info(&pf->pdev->dev,\n-\t\t\t\t \"add filter failed on %s, err %s aq_err %s\\n\",\n-\t\t\t\t vsi_name,\n-\t\t\t\t i40e_stat_str(hw, aq_ret),\n-\t\t\t\t i40e_aq_str(hw, aq_err));\n-\t\t\tif ((hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) &&\n-\t\t\t    !test_bit(__I40E_FILTER_OVERFLOW_PROMISC,\n-\t\t\t\t      &vsi->state)) {\n-\t\t\t\tpromisc_forced_on = true;\n-\t\t\t\tset_bit(__I40E_FILTER_OVERFLOW_PROMISC,\n-\t\t\t\t\t&vsi->state);\n-\t\t\t\tdev_info(&pf->pdev->dev, \"promiscuous mode forced on %s\\n\",\n-\t\t\t\t\t vsi_name);\n-\t\t\t}\n+\t\t\t\t \"filter logjam cleared on %s, leaving overflow promiscuous mode\\n\",\n+\t\t\t\t vsi_name);\n+\t\t\tclear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);\n+\t\t\tpromisc_changed = true;\n+\t\t\tvsi->promisc_threshold = 0;\n \t\t}\n \t}\n \n@@ -2115,7 +2115,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)\n \t\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n \t\t}\n \t}\n-\tif ((changed_flags & IFF_PROMISC) || promisc_forced_on) {\n+\tif ((changed_flags & IFF_PROMISC) ||\n+\t    (promisc_changed &&\n+\t     test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))) {\n \t\tbool cur_promisc;\n \n \t\tcur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||\n@@ -2352,7 +2354,7 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)\n  **/\n int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n {\n-\tstruct i40e_mac_filter *f, *add_f;\n+\tstruct i40e_mac_filter *f, *ftmp, *add_f;\n \tbool is_netdev, is_vf;\n \n \tis_vf = (vsi->type == I40E_VSI_SRIOV);\n@@ -2373,7 +2375,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t\t}\n \t}\n \n-\tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n+\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {\n \t\tadd_f = i40e_add_filter(vsi, f->macaddr, vid, is_vf, is_netdev);\n \t\tif (!add_f) {\n \t\t\tdev_info(&vsi->back->pdev->dev,\n@@ -2387,7 +2389,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \t/* Now if we add a vlan tag, make sure to check if it is the first\n \t * tag (i.e. a \"tag\" -1 does exist) and if so replace the -1 \"tag\"\n \t * with 0, so we now accept untagged and specified tagged traffic\n-\t * (and not any taged and untagged)\n+\t * (and not all tags along with untagged)\n \t */\n \tif (vid > 0) {\n \t\tif (is_netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr,\n@@ -2409,7 +2411,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n \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\tlist_for_each_entry_safe(f, ftmp, &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\tcontinue;\n@@ -2446,7 +2448,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)\n int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n {\n \tstruct net_device *netdev = vsi->netdev;\n-\tstruct i40e_mac_filter *f, *add_f;\n+\tstruct i40e_mac_filter *f, *ftmp, *add_f;\n \tbool is_vf, is_netdev;\n \tint filter_count = 0;\n \n@@ -2459,7 +2461,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n \tif (is_netdev)\n \t\ti40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev);\n \n-\tlist_for_each_entry(f, &vsi->mac_filter_list, list)\n+\tlist_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)\n \t\ti40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev);\n \n \t/* go through all the filters for this VSI and if there is only\n@@ -2492,7 +2494,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)\n \t}\n \n \tif (!filter_count) {\n-\t\tlist_for_each_entry(f, &vsi->mac_filter_list, list) {\n+\t\tlist_for_each_entry_safe(f, ftmp, &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\tis_vf, is_netdev);\n@@ -2537,8 +2539,6 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,\n \tif (vid > 4095)\n \t\treturn -EINVAL;\n \n-\tnetdev_info(netdev, \"adding %pM vid=%d\\n\", netdev->dev_addr, vid);\n-\n \t/* If the network stack called us with vid = 0 then\n \t * it is asking to receive priority tagged packets with\n \t * vlan id 0.  Our HW receives them by default when configured\n@@ -2572,8 +2572,6 @@ static int i40e_vlan_rx_kill_vid(struct net_device *netdev,\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n \tstruct i40e_vsi *vsi = np->vsi;\n \n-\tnetdev_info(netdev, \"removing %pM vid=%d\\n\", netdev->dev_addr, vid);\n-\n \t/* return code is ignored as there is nothing a user\n \t * can do about failure to remove and a log message was\n \t * already printed from the other function\n@@ -9080,7 +9078,6 @@ static const struct net_device_ops i40e_netdev_ops = {\n  **/\n static int i40e_config_netdev(struct i40e_vsi *vsi)\n {\n-\tu8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\n \tstruct i40e_pf *pf = vsi->back;\n \tstruct i40e_hw *hw = &pf->hw;\n \tstruct i40e_netdev_priv *np;\n@@ -9144,18 +9141,10 @@ 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\t\tspin_lock_bh(&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_bh(&vsi->mac_filter_list_lock);\n-\t\t}\n-\t} else if ((pf->hw.aq.api_maj_ver > 1) ||\n-\t\t   ((pf->hw.aq.api_maj_ver == 1) &&\n-\t\t    (pf->hw.aq.api_min_ver > 4))) {\n-\t\t/* Supported in FW API version higher than 1.4 */\n-\t\tpf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;\n-\t\tpf->auto_disable_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;\n+\t\ti40e_rm_default_mac_filter(vsi, mac_addr);\n+\t\tspin_lock_bh(&vsi->mac_filter_list_lock);\n+\t\ti40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true);\n+\t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\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@@ -9167,10 +9156,6 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)\n \t\tspin_unlock_bh(&vsi->mac_filter_list_lock);\n \t}\n \n-\tspin_lock_bh(&vsi->mac_filter_list_lock);\n-\ti40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false);\n-\tspin_unlock_bh(&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 \n@@ -9249,8 +9234,6 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)\n {\n \tint ret = -ENODEV;\n \ti40e_status aq_ret = 0;\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@@ -9438,7 +9421,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)\n \t\tvsi->seid = ctxt.seid;\n \t\tvsi->id = ctxt.vsi_number;\n \t}\n-\t/* Except FDIR VSI, for all othet VSI set the broadcast filter */\n+\t/* Except FDIR VSI, for all other VSI set the broadcast filter */\n \tif (vsi->type != I40E_VSI_FDIR) {\n \t\taq_ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL);\n \t\tif (aq_ret) {\n@@ -9451,41 +9434,16 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)\n \t\t}\n \t}\n \n+\tvsi->active_filters = 0;\n+\tclear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);\n \tspin_lock_bh(&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->state = I40E_FILTER_NEW;\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\tether_addr_copy(laa_macaddr, f->macaddr);\n-\t\t\tfound_laa_mac_filter = true;\n-\t\t}\n \t}\n \tspin_unlock_bh(&vsi->mac_filter_list_lock);\n \n-\tif (found_laa_mac_filter) {\n-\t\tstruct i40e_aqc_remove_macvlan_element_data element;\n-\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@@ -9696,6 +9654,8 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)\n \tpf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0;\n \tpf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid;\n \ti40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc);\n+\tif (vsi->type == I40E_VSI_MAIN)\n+\t\ti40e_rm_default_mac_filter(vsi, pf->hw.mac.perm_addr);\n \n \t/* assign it some queues */\n \tret = i40e_alloc_rings(vsi);\n",
    "prefixes": [
        "next",
        "PTACH",
        "S38-v2",
        "6/7"
    ]
}