Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/564181/?format=api
{ "id": 564181, "url": "http://patchwork.ozlabs.org/api/patches/564181/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20160107071118.13648.98637.stgit@localhost.localdomain/", "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": "<20160107071118.13648.98637.stgit@localhost.localdomain>", "list_archive_url": null, "date": "2016-01-07T07:11:18", "name": "[next,08/11] igb: Add support for VLAN promiscuous with SR-IOV and NTUPLE", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "c54ecdb34df4d6bcbda12a6d98ad252b8c19da86", "submitter": { "id": 67293, "url": "http://patchwork.ozlabs.org/api/people/67293/?format=api", "name": "Alexander Duyck", "email": "aduyck@mirantis.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/20160107071118.13648.98637.stgit@localhost.localdomain/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/564181/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/564181/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 silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ozlabs.org (Postfix) with ESMTP id 9E2231402C0\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 7 Jan 2016 18:11:26 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id EB17332D9D;\n\tThu, 7 Jan 2016 07:11:25 +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 zVby9SlmRKva; Thu, 7 Jan 2016 07:11:23 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id C1FDC32D95;\n\tThu, 7 Jan 2016 07:11:23 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 7AB401C09CE\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Jan 2016 07:11:22 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 764E09338C\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Jan 2016 07:11:22 +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 0Ll7423v1z8q for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Jan 2016 07:11:21 +0000 (UTC)", "from mail-pa0-f48.google.com (mail-pa0-f48.google.com\n\t[209.85.220.48])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 5773A9338B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 7 Jan 2016 07:11:21 +0000 (UTC)", "by mail-pa0-f48.google.com with SMTP id cy9so251598249pac.0\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 06 Jan 2016 23:11:21 -0800 (PST)", "from localhost.localdomain\n\t(static-50-53-29-36.bvtn.or.frontiernet.net. [50.53.29.36])\n\tby smtp.gmail.com with ESMTPSA id\n\tq8sm147709532pap.45.2016.01.06.23.11.19\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tWed, 06 Jan 2016 23:11:20 -0800 (PST)" ], "Authentication-Results": "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=mirantis.com header.i=@mirantis.com\n\theader.b=QK9hXMYc; dkim-atps=neutral", "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "from auto-whitelisted by SQLgrey-1.7.6", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=mirantis.com;\n\ts=google; \n\th=subject:from:to:cc:date:message-id:in-reply-to:references\n\t:user-agent:mime-version:content-type:content-transfer-encoding;\n\tbh=EnbIZ3/7gNKJVQIqzQTlx6cnvO+8FdKfhWpCA7gzzOA=;\n\tb=QK9hXMYcBu2ueqqRbaNtBvNDsloNYFHECymwYDOih25F4aVksCFbEhxgXUajMfaX6E\n\tM5STgIG8Ke+JdOFD9soxIpzww93gv5Xdhobp4rWtgGOuf4nlpQ68lV772+olTQYjsTFZ\n\tceXDA82CuI5HMQTb2vDgq+RoUtGjs53Zuas8c=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to\n\t:references:user-agent:mime-version:content-type\n\t:content-transfer-encoding;\n\tbh=EnbIZ3/7gNKJVQIqzQTlx6cnvO+8FdKfhWpCA7gzzOA=;\n\tb=XDgyt5EV26zvnkBAXdJPcGc5xwP+cLatX2JY3CUMjcB/+1FPQtSNytHS1FtZH0UP+q\n\tx1Yy2JO4rHPJxXT+Oex17xt0pDMUt40GVxWyCtQ2pPQh+o4i1p/KSzkSJb3j76QzPaaW\n\tutw9d6luwIlOz1RAkdgRhw4nOBAd5ZK/qAX7M31FTdhQ1DHwV2fXPdVu/Av1uSFBsnV3\n\tYtlZ17kBC/H1f2KHgOeic4pdJY9jwF1lOxODI7WIYuwiXLfYbrLQWWGzkYifzZPxiFSs\n\t+uR4jTF+alw5mH6vx4hMmN0+3xWsY56m85yhnti52t7vcQqzjm6DggmKH0uJWJufeXy0\n\tgukA==", "X-Gm-Message-State": "ALoCoQm0Gre2y/ZEKOXjgV0t/HZgtI171cMQWxI7AqBAzzQ8uBwd8USqIiHn3RvQJkVG0xnAKah85mqwzwueJO7UHSjgypjvdw==", "X-Received": "by 10.66.219.163 with SMTP id pp3mr144726189pac.55.1452150681048;\n\tWed, 06 Jan 2016 23:11:21 -0800 (PST)", "From": "Alexander Duyck <aduyck@mirantis.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Wed, 06 Jan 2016 23:11:18 -0800", "Message-ID": "<20160107071118.13648.98637.stgit@localhost.localdomain>", "In-Reply-To": "<20160107070850.13648.21033.stgit@localhost.localdomain>", "References": "<20160107070850.13648.21033.stgit@localhost.localdomain>", "User-Agent": "StGit/0.17.1-dirty", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [next PATCH 08/11] igb: Add support for VLAN\n\tpromiscuous with SR-IOV and NTUPLE", "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>", "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": "This change fixes things so that we can fully support SR-IOV or the\nrecently added NTUPLE filtering while allowing support for VLAN promiscuous\nmode. By making this change we are able to support possible scenarios such\nas SR-IOV with the PF connected to a Linux bridge hosting other VMs.\n\nSigned-off-by: Alexander Duyck <aduyck@mirantis.com>\n---\n drivers/net/ethernet/intel/igb/igb.h | 1 \n drivers/net/ethernet/intel/igb/igb_main.c | 313 ++++++++++++++++++++++-------\n 2 files changed, 242 insertions(+), 72 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h\nindex d557e99eab6c..386e2bf80bdd 100644\n--- a/drivers/net/ethernet/intel/igb/igb.h\n+++ b/drivers/net/ethernet/intel/igb/igb.h\n@@ -543,6 +543,7 @@ struct igb_nfc_filter {\n #define IGB_FLAG_MAS_ENABLE\t\t(1 << 12)\n #define IGB_FLAG_HAS_MSIX\t\t(1 << 13)\n #define IGB_FLAG_EEE\t\t\t(1 << 14)\n+#define IGB_FLAG_VLAN_PROMISC\t\tBIT(15)\n \n /* Media Auto Sense */\n #define IGB_MAS_ENABLE_0\t\t0X0001\ndiff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c\nindex cf91aae2a413..04a23230c4dc 100644\n--- a/drivers/net/ethernet/intel/igb/igb_main.c\n+++ b/drivers/net/ethernet/intel/igb/igb_main.c\n@@ -1848,6 +1848,10 @@ void igb_down(struct igb_adapter *adapter)\n \n \tif (!pci_channel_offline(adapter->pdev))\n \t\tigb_reset(adapter);\n+\n+\t/* clear VLAN promisc flag so VFTA will be updated if necessary */\n+\tadapter->flags &= ~IGB_FLAG_VLAN_PROMISC;\n+\n \tigb_clean_all_tx_rings(adapter);\n \tigb_clean_all_rx_rings(adapter);\n #ifdef CONFIG_IGB_DCA\n@@ -2081,7 +2085,7 @@ static int igb_set_features(struct net_device *netdev,\n \tif (changed & NETIF_F_HW_VLAN_CTAG_RX)\n \t\tigb_vlan_mode(netdev, features);\n \n-\tif (!(changed & NETIF_F_RXALL))\n+\tif (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))\n \t\treturn 0;\n \n \tif (!(features & NETIF_F_NTUPLE)) {\n@@ -3635,8 +3639,7 @@ void igb_setup_rctl(struct igb_adapter *adapter)\n \t\t\t E1000_RCTL_BAM | /* RX All Bcast Pkts */\n \t\t\t E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */\n \n-\t\trctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */\n-\t\t\t E1000_RCTL_DPF | /* Allow filtered pause */\n+\t\trctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */\n \t\t\t E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */\n \t\t/* Do not mess with E1000_CTRL_VME, it affects transmit as well,\n \t\t * and that breaks VLANs.\n@@ -4091,6 +4094,130 @@ static int igb_write_uc_addr_list(struct net_device *netdev)\n \treturn count;\n }\n \n+static int igb_vlan_promisc_enable(struct igb_adapter *adapter)\n+{\n+\tstruct e1000_hw *hw = &adapter->hw;\n+\tu32 i, pf_id;\n+\n+\tswitch (hw->mac.type) {\n+\tcase e1000_i210:\n+\tcase e1000_i211:\n+\tcase e1000_i350:\n+\t\t/* VLAN filtering needed for VLAN prio filter */\n+\t\tif (adapter->netdev->features & NETIF_F_NTUPLE)\n+\t\t\tbreak;\n+\t\t/* fall through */\n+\tcase e1000_82576:\n+\tcase e1000_82580:\n+\tcase e1000_i354:\n+\t\t/* VLAN filtering needed for pool filtering */\n+\t\tif (adapter->vfs_allocated_count)\n+\t\t\tbreak;\n+\t\t/* fall through */\n+\tdefault:\n+\t\treturn 1;\n+\t}\n+\n+\t/* We are already in VLAN promisc, nothing to do */\n+\tif (adapter->flags & IGB_FLAG_VLAN_PROMISC)\n+\t\treturn 0;\n+\n+\tif (!adapter->vfs_allocated_count)\n+\t\tgoto set_vfta;\n+\n+\t/* Add PF to all active pools */\n+\tpf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT;\n+\n+\tfor (i = E1000_VLVF_ARRAY_SIZE; --i;) {\n+\t\tu32 vlvf = rd32(E1000_VLVF(i));\n+\n+\t\tvlvf |= 1 << pf_id;\n+\t\twr32(E1000_VLVF(i), vlvf);\n+\t}\n+\n+set_vfta:\n+\t/* Set all bits in the VLAN filter table array */\n+\tfor (i = E1000_VLAN_FILTER_TBL_SIZE; i--;)\n+\t\thw->mac.ops.write_vfta(hw, i, ~0U);\n+\n+\t/* Set flag so we don't redo unnecessary work */\n+\tadapter->flags |= IGB_FLAG_VLAN_PROMISC;\n+\n+\treturn 0;\n+}\n+\n+#define VFTA_BLOCK_SIZE 8\n+static void igb_scrub_vfta(struct igb_adapter *adapter, u32 vfta_offset)\n+{\n+\tstruct e1000_hw *hw = &adapter->hw;\n+\tu32 vfta[VFTA_BLOCK_SIZE] = { 0 };\n+\tu32 vid_start = vfta_offset * 32;\n+\tu32 vid_end = vid_start + (VFTA_BLOCK_SIZE * 32);\n+\tu32 i, vid, word, bits, pf_id;\n+\n+\t/* guarantee that we don't scrub out management VLAN */\n+\tvid = adapter->mng_vlan_id;\n+\tif (vid >= vid_start && vid < vid_end)\n+\t\tvfta[(vid - vid_start) / 32] |= 1 << (vid % 32);\n+\n+\tif (!adapter->vfs_allocated_count)\n+\t\tgoto set_vfta;\n+\n+\tpf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT;\n+\n+\tfor (i = E1000_VLVF_ARRAY_SIZE; --i;) {\n+\t\tu32 vlvf = rd32(E1000_VLVF(i));\n+\n+\t\t/* pull VLAN ID from VLVF */\n+\t\tvid = vlvf & VLAN_VID_MASK;\n+\n+\t\t/* only concern ourselves with a certain range */\n+\t\tif (vid < vid_start || vid >= vid_end)\n+\t\t\tcontinue;\n+\n+\t\tif (vlvf & E1000_VLVF_VLANID_ENABLE) {\n+\t\t\t/* record VLAN ID in VFTA */\n+\t\t\tvfta[(vid - vid_start) / 32] |= 1 << (vid % 32);\n+\n+\t\t\t/* if PF is part of this then continue */\n+\t\t\tif (test_bit(vid, adapter->active_vlans))\n+\t\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* remove PF from the pool */\n+\t\tbits = ~(1 << pf_id);\n+\t\tbits &= rd32(E1000_VLVF(i));\n+\t\twr32(E1000_VLVF(i), bits);\n+\t}\n+\n+set_vfta:\n+\t/* extract values from active_vlans and write back to VFTA */\n+\tfor (i = VFTA_BLOCK_SIZE; i--;) {\n+\t\tvid = (vfta_offset + i) * 32;\n+\t\tword = vid / BITS_PER_LONG;\n+\t\tbits = vid % BITS_PER_LONG;\n+\n+\t\tvfta[i] |= adapter->active_vlans[word] >> bits;\n+\n+\t\thw->mac.ops.write_vfta(hw, vfta_offset + i, vfta[i]);\n+\t}\n+}\n+\n+static void igb_vlan_promisc_disable(struct igb_adapter *adapter)\n+{\n+\tu32 i;\n+\n+\t/* We are not in VLAN promisc, nothing to do */\n+\tif (!(adapter->flags & IGB_FLAG_VLAN_PROMISC))\n+\t\treturn;\n+\n+\t/* Set flag so we don't redo unnecessary work */\n+\tadapter->flags &= ~IGB_FLAG_VLAN_PROMISC;\n+\n+\tfor (i = 0; i < E1000_VLAN_FILTER_TBL_SIZE; i += VFTA_BLOCK_SIZE)\n+\t\tigb_scrub_vfta(adapter, i);\n+}\n+\n /**\n * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set\n * @netdev: network interface device structure\n@@ -4105,21 +4232,13 @@ static void igb_set_rx_mode(struct net_device *netdev)\n \tstruct igb_adapter *adapter = netdev_priv(netdev);\n \tstruct e1000_hw *hw = &adapter->hw;\n \tunsigned int vfn = adapter->vfs_allocated_count;\n-\tu32 rctl, vmolr = 0;\n+\tu32 rctl = 0, vmolr = 0;\n \tint count;\n \n \t/* Check for Promiscuous and All Multicast modes */\n-\trctl = rd32(E1000_RCTL);\n-\n-\t/* clear the effected bits */\n-\trctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE);\n-\n \tif (netdev->flags & IFF_PROMISC) {\n-\t\t/* retain VLAN HW filtering if in VT mode */\n-\t\tif (adapter->vfs_allocated_count)\n-\t\t\trctl |= E1000_RCTL_VFE;\n-\t\trctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);\n-\t\tvmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME);\n+\t\trctl |= E1000_RCTL_UPE | E1000_RCTL_MPE;\n+\t\tvmolr |= E1000_VMOLR_ROPE | E1000_VMOLR_MPME;\n \t} else {\n \t\tif (netdev->flags & IFF_ALLMULTI) {\n \t\t\trctl |= E1000_RCTL_MPE;\n@@ -4146,8 +4265,24 @@ static void igb_set_rx_mode(struct net_device *netdev)\n \t\t\trctl |= E1000_RCTL_UPE;\n \t\t\tvmolr |= E1000_VMOLR_ROPE;\n \t\t}\n-\t\trctl |= E1000_RCTL_VFE;\n \t}\n+\n+\t/* enable VLAN filtering by default */\n+\trctl |= E1000_RCTL_VFE;\n+\n+\t/* disable VLAN filtering for modes that require it */\n+\tif ((netdev->flags & IFF_PROMISC) ||\n+\t (netdev->features & NETIF_F_RXALL)) {\n+\t\t/* if we fail to set all rules then just clear VFE */\n+\t\tif (igb_vlan_promisc_enable(adapter))\n+\t\t\trctl &= ~E1000_RCTL_VFE;\n+\t} else {\n+\t\tigb_vlan_promisc_disable(adapter);\n+\t}\n+\n+\t/* update state of unicast, multicast, and VLAN filtering modes */\n+\trctl |= rd32(E1000_RCTL) & ~(E1000_RCTL_UPE | E1000_RCTL_MPE |\n+\t\t\t\t E1000_RCTL_VFE);\n \twr32(E1000_RCTL, rctl);\n \n \t/* In order to support SR-IOV and eventually VMDq it is necessary to set\n@@ -5890,48 +6025,98 @@ static void igb_restore_vf_multicasts(struct igb_adapter *adapter)\n static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf)\n {\n \tstruct e1000_hw *hw = &adapter->hw;\n-\tu32 pool_mask, reg, vid;\n-\tint i;\n+\tu32 pool_mask, vlvf_mask, i;\n+\n+\t/* create mask for VF and other pools */\n+\tpool_mask = E1000_VLVF_POOLSEL_MASK;\n+\tvlvf_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf);\n \n-\tpool_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf);\n+\t/* drop PF from pool bits */\n+\tpool_mask &= ~(1 << (E1000_VLVF_POOLSEL_SHIFT +\n+\t\t\t adapter->vfs_allocated_count));\n \n \t/* Find the vlan filter for this id */\n-\tfor (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {\n-\t\treg = rd32(E1000_VLVF(i));\n+\tfor (i = E1000_VLVF_ARRAY_SIZE; i--;) {\n+\t\tu32 vlvf = rd32(E1000_VLVF(i));\n+\t\tu32 vfta_mask, vid, vfta;\n \n \t\t/* remove the vf from the pool */\n-\t\treg &= ~pool_mask;\n-\n-\t\t/* if pool is empty then remove entry from vfta */\n-\t\tif (!(reg & E1000_VLVF_POOLSEL_MASK) &&\n-\t\t (reg & E1000_VLVF_VLANID_ENABLE)) {\n-\t\t\treg = 0;\n-\t\t\tvid = reg & E1000_VLVF_VLANID_MASK;\n-\t\t\tigb_vfta_set(hw, vid, vf, false, true);\n-\t\t}\n+\t\tif (!(vlvf & vlvf_mask))\n+\t\t\tcontinue;\n+\n+\t\t/* clear out bit from vlvf */\n+\t\tvlvf ^= vlvf_mask;\n+\n+\t\t/* if other pools are present, just remove ourselves */\n+\t\tif (vlvf & pool_mask)\n+\t\t\tgoto update_vlvfb;\n+\n+\t\t/* if PF is present, leave VFTA */\n+\t\tif (vlvf & E1000_VLVF_POOLSEL_MASK)\n+\t\t\tgoto update_vlvf;\n+\n+\t\tvid = vlvf & E1000_VLVF_VLANID_MASK;\n+\t\tvfta_mask = 1 << (vid % 32);\n \n-\t\twr32(E1000_VLVF(i), reg);\n+\t\t/* clear bit from VFTA */\n+\t\tvfta = adapter->shadow_vfta[vid / 32];\n+\t\tif (vfta & vfta_mask)\n+\t\t\thw->mac.ops.write_vfta(hw, vid / 32, vfta ^ vfta_mask);\n+update_vlvf:\n+\t\t/* clear pool selection enable */\n+\t\tif (adapter->flags & IGB_FLAG_VLAN_PROMISC)\n+\t\t\tvlvf &= E1000_VLVF_POOLSEL_MASK;\n+\t\telse\n+\t\t\tvlvf = 0;\n+update_vlvfb:\n+\t\t/* clear pool bits */\n+\t\twr32(E1000_VLVF(i), vlvf);\n \t}\n }\n \n-static int igb_find_vlvf_entry(struct igb_adapter *adapter, int vid)\n+static int igb_find_vlvf_entry(struct e1000_hw *hw, u32 vlan)\n {\n-\tstruct e1000_hw *hw = &adapter->hw;\n-\tint i;\n-\tu32 reg;\n+\tu32 vlvf;\n+\tint idx;\n \n-\t/* Find the vlan filter for this id */\n-\tfor (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {\n-\t\treg = rd32(E1000_VLVF(i));\n-\t\tif ((reg & E1000_VLVF_VLANID_ENABLE) &&\n-\t\t vid == (reg & E1000_VLVF_VLANID_MASK))\n+\t/* short cut the special case */\n+\tif (vlan == 0)\n+\t\treturn 0;\n+\n+\t/* Search for the vlan id in the VLVF entries */\n+\tfor (idx = E1000_VLVF_ARRAY_SIZE; --idx;) {\n+\t\tvlvf = rd32(E1000_VLVF(idx));\n+\t\tif ((vlvf & VLAN_VID_MASK) == vlan)\n \t\t\tbreak;\n \t}\n \n-\tif (i >= E1000_VLVF_ARRAY_SIZE)\n-\t\ti = -1;\n+\treturn idx;\n+}\n+\n+void igb_update_pf_vlvf(struct igb_adapter *adapter, u32 vid)\n+{\n+\tstruct e1000_hw *hw = &adapter->hw;\n+\tu32 bits, pf_id;\n+\tint idx;\n+\n+\tidx = igb_find_vlvf_entry(hw, vid);\n+\tif (!idx)\n+\t\treturn;\n \n-\treturn i;\n+\t/* See if any other pools are set for this VLAN filter\n+\t * entry other than the PF.\n+\t */\n+\tpf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT;\n+\tbits = ~(1 << pf_id) & E1000_VLVF_POOLSEL_MASK;\n+\tbits &= rd32(E1000_VLVF(idx));\n+\n+\t/* Disable the filter so this falls into the default pool. */\n+\tif (!bits) {\n+\t\tif (adapter->flags & IGB_FLAG_VLAN_PROMISC)\n+\t\t\twr32(E1000_VLVF(idx), 1 << pf_id);\n+\t\telse\n+\t\t\twr32(E1000_VLVF(idx), 0);\n+\t}\n }\n \n static s32 igb_set_vf_vlan(struct igb_adapter *adapter, u32 vid,\n@@ -5946,7 +6131,7 @@ static s32 igb_set_vf_vlan(struct igb_adapter *adapter, u32 vid,\n \t * redundant but it guarantees PF will maintain visibility to\n \t * the VLAN.\n \t */\n-\tif (add && (adapter->netdev->flags & IFF_PROMISC)) {\n+\tif (add && test_bit(vid, adapter->active_vlans)) {\n \t\terr = igb_vfta_set(hw, vid, pf_id, true, false);\n \t\tif (err)\n \t\t\treturn err;\n@@ -5954,36 +6139,17 @@ static s32 igb_set_vf_vlan(struct igb_adapter *adapter, u32 vid,\n \n \terr = igb_vfta_set(hw, vid, vf, add, false);\n \n-\tif (err)\n-\t\tgoto out;\n+\tif (add && !err)\n+\t\treturn err;\n \n-\t/* Go through all the checks to see if the VLAN filter should\n-\t * be wiped completely.\n+\t/* If we failed to add the VF VLAN or we are removing the VF VLAN\n+\t * we may need to drop the PF pool bit in order to allow us to free\n+\t * up the VLVF resources.\n \t */\n-\tif (!add && (adapter->netdev->flags & IFF_PROMISC)) {\n-\t\tu32 vlvf, bits;\n-\t\tint regndx = igb_find_vlvf_entry(adapter, vid);\n-\n-\t\tif (regndx < 0)\n-\t\t\tgoto out;\n-\t\t/* See if any other pools are set for this VLAN filter\n-\t\t * entry other than the PF.\n-\t\t */\n-\t\tvlvf = bits = rd32(E1000_VLVF(regndx));\n-\t\tbits &= 1 << (E1000_VLVF_POOLSEL_SHIFT +\n-\t\t\t adapter->vfs_allocated_count);\n-\t\t/* If the filter was removed then ensure PF pool bit\n-\t\t * is cleared if the PF only added itself to the pool\n-\t\t * because the PF is in promiscuous mode.\n-\t\t */\n-\t\tif ((vlvf & VLAN_VID_MASK) == vid &&\n-\t\t !test_bit(vid, adapter->active_vlans) &&\n-\t\t !bits)\n-\t\t\tigb_vfta_set(hw, vid, adapter->vfs_allocated_count,\n-\t\t\t\t false, false);\n-\t}\n+\tif (test_bit(vid, adapter->active_vlans) ||\n+\t (adapter->flags & IGB_FLAG_VLAN_PROMISC))\n+\t\tigb_update_pf_vlvf(adapter, vid);\n \n-out:\n \treturn err;\n }\n \n@@ -7260,7 +7426,9 @@ static int igb_vlan_rx_add_vid(struct net_device *netdev,\n \tint pf_id = adapter->vfs_allocated_count;\n \n \t/* add the filter since PF can receive vlans w/o entry in vlvf */\n-\tigb_vfta_set(hw, vid, pf_id, true, true);\n+\tif (!vid || !(adapter->flags & IGB_FLAG_VLAN_PROMISC))\n+\t\tigb_vfta_set(hw, vid, pf_id, true, !!vid);\n+\n \tset_bit(vid, adapter->active_vlans);\n \n \treturn 0;\n@@ -7274,7 +7442,8 @@ static int igb_vlan_rx_kill_vid(struct net_device *netdev,\n \tstruct e1000_hw *hw = &adapter->hw;\n \n \t/* remove VID from filter table */\n-\tigb_vfta_set(hw, vid, pf_id, false, true);\n+\tif (vid && !(adapter->flags & IGB_FLAG_VLAN_PROMISC))\n+\t\tigb_vfta_set(hw, vid, pf_id, false, true);\n \n \tclear_bit(vid, adapter->active_vlans);\n \n", "prefixes": [ "next", "08/11" ] }