Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/806376/?format=api
{ "id": 806376, "url": "http://patchwork.ozlabs.org/api/patches/806376/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170828061843.24349-3-sam@mendozajonas.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170828061843.24349-3-sam@mendozajonas.com>", "list_archive_url": null, "date": "2017-08-28T06:18:42", "name": "[net-next,v3,2/3] net/ncsi: Configure VLAN tag filter", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": true, "hash": "bc826f0d8323cd3f9ab906187dae6ae41de3db82", "submitter": { "id": 68013, "url": "http://patchwork.ozlabs.org/api/people/68013/?format=api", "name": "Sam Mendoza-Jonas", "email": "sam@mendozajonas.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170828061843.24349-3-sam@mendozajonas.com/mbox/", "series": [ { "id": 78, "url": "http://patchwork.ozlabs.org/api/series/78/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=78", "date": "2017-08-28T06:18:41", "name": "NCSI VLAN Filtering Support", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/78/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/806376/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/806376/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=\"nbhyz3oo\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=messagingengine.com\n\theader.i=@messagingengine.com header.b=\"oeFt3/dY\"; \n\tdkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xghSj115rz9s7m\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 28 Aug 2017 16:19:49 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751237AbdH1GTG (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 28 Aug 2017 02:19:06 -0400", "from out2-smtp.messagingengine.com ([66.111.4.26]:47427 \"EHLO\n\tout2-smtp.messagingengine.com\" rhost-flags-OK-OK-OK-OK)\n\tby vger.kernel.org with ESMTP id S1751227AbdH1GTD (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 28 Aug 2017 02:19:03 -0400", "from compute2.internal (compute2.nyi.internal [10.202.2.42])\n\tby mailout.nyi.internal (Postfix) with ESMTP id 41C9020DE1;\n\tMon, 28 Aug 2017 02:19:03 -0400 (EDT)", "from frontend1 ([10.202.2.160])\n\tby compute2.internal (MEProxy); Mon, 28 Aug 2017 02:19:03 -0400", "from v4.ozlabs.ibm.com (unknown [122.99.82.10])\n\tby mail.messagingengine.com (Postfix) with ESMTPA id 2054A7E271;\n\tMon, 28 Aug 2017 02:18:59 -0400 (EDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/relaxed; d=\n\tmendozajonas.com; h=cc:date:from:in-reply-to:message-id\n\t:references:subject:to:x-me-sender:x-me-sender:x-sasl-enc\n\t:x-sasl-enc; s=fm1; bh=3tQYV5rCtjqdK0ACPaw/bmizGokKMFhn1r/PLJMby\n\tbM=; b=nbhyz3ooCTHUBGzDMOMubVtetuUP9AvvASyBAQCiI/10hqlKxSa7QIl6Q\n\tar+PHl8lIXWCJGxhCsW0VJJNbziQktDwmdBY8uNE1EJrff6QkUDmjmyxDWCPX1wd\n\teM9btBhSN4zGaJZb0fIxGcaeWtQCePFbrsUoWz+/B+b4BMJx5xK2FVTeePQPmke/\n\tY7FbeN5FohHTdFIHf1hk39udj+UYgNczgkTl1mZAJj02UsqgiC26ujYXJzLyynNY\n\tS06j670EWwuyTB1Qsm3yIlfrHgnJl7zdkuTzLNIWLi0rdQfLla2/QABOXdDA7FYK\n\tX9uWta7acVCiZs6eFjk/UNWcw03TA==", "v=1; a=rsa-sha256; c=relaxed/relaxed; d=\n\tmessagingengine.com; h=cc:date:from:in-reply-to:message-id\n\t:references:subject:to:x-me-sender:x-me-sender:x-sasl-enc\n\t:x-sasl-enc; s=fm1; bh=3tQYV5rCtjqdK0ACPaw/bmizGokKMFhn1r/PLJMby\n\tbM=; b=oeFt3/dYWp16YqlhWCXuNqHIV/o0VEiGmxRqsrfd0QmXOysB4Rrfealkw\n\tqQ0Gm/gXwLkyftgX9ZL9osTMb1VEonxteoRl/S5OWdS8XgWZd37rliKU80lLCZ1R\n\tUrsJECIE3bqZWhS7ZJu5NPxfYIzrtbn31ABhROpr3ZsEdGq1UjTuowpKolu1ovTk\n\tSxbDKRtkNIgZq9En38KwSQPpKgyNMPetl0ZhSG2f3whc7SDyUFxTdac3Hc9THW6p\n\tpk0l5dKG3/QqE1tvTNRBPnXt5fjdeBd4+SdwC4+pTZbNLzh0+wVx5XFzeRhDLgf8\n\tovIduFbAtpZ1tYG7y7+T+GRZUHgHg==" ], "X-ME-Sender": "<xms:17WjWf2i_NhAi1pGB2TMfwWtzXGHjDHs-u-KrzQ3yjiQpenh1ohPKA>", "X-Sasl-enc": "9ftzqka1stQ5oA8pRiDkaL3il/zLmUZIc/gq6jAU0wYS 1503901142", "From": "Samuel Mendoza-Jonas <sam@mendozajonas.com>", "To": "\"David S . Miller\" <davem@davemloft.net>, netdev@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, OpenBMC Maillist <openbmc@lists.ozlabs.org>", "Cc": "Samuel Mendoza-Jonas <sam@mendozajonas.com>,\n\tJoel Stanley <joel@jms.id.au>,\n\tBenjamin Herrenschmidt <benh@kernel.crashing.org>,\n\tGavin Shan <gwshan@linux.vnet.ibm.com>, ratagupt@in.ibm.com", "Subject": "[PATCH net-next v3 2/3] net/ncsi: Configure VLAN tag filter", "Date": "Mon, 28 Aug 2017 16:18:42 +1000", "Message-Id": "<20170828061843.24349-3-sam@mendozajonas.com>", "X-Mailer": "git-send-email 2.14.0", "In-Reply-To": "<20170828061843.24349-1-sam@mendozajonas.com>", "References": "<20170828061843.24349-1-sam@mendozajonas.com>", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Make use of the ndo_vlan_rx_{add,kill}_vid callbacks to have the NCSI\nstack process new VLAN tags and configure the channel VLAN filter\nappropriately.\nSeveral VLAN tags can be set and a \"Set VLAN Filter\" packet must be sent\nfor each one, meaning the ncsi_dev_state_config_svf state must be\nrepeated. An internal list of VLAN tags is maintained, and compared\nagainst the current channel's ncsi_channel_filter in order to keep track\nwithin the state. VLAN filters are removed in a similar manner, with the\nintroduction of the ncsi_dev_state_config_clear_vids state. The maximum\nnumber of VLAN tag filters is determined by the \"Get Capabilities\"\nresponse from the channel.\n\nSigned-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>\n---\nv3:\t- Add comment describing change to ncsi_find_filter()\n\t- Catch NULL in clear_one_vid() from ncsi_get_filter()\n\t- Simplify state changes when kicking updated channel\n\n include/net/ncsi.h | 2 +\n net/ncsi/internal.h | 11 ++\n net/ncsi/ncsi-manage.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++-\n net/ncsi/ncsi-rsp.c | 9 +-\n 4 files changed, 326 insertions(+), 4 deletions(-)", "diff": "diff --git a/include/net/ncsi.h b/include/net/ncsi.h\nindex 68680baac0fd..1f96af46df49 100644\n--- a/include/net/ncsi.h\n+++ b/include/net/ncsi.h\n@@ -28,6 +28,8 @@ struct ncsi_dev {\n };\n \n #ifdef CONFIG_NET_NCSI\n+int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid);\n+int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid);\n struct ncsi_dev *ncsi_register_dev(struct net_device *dev,\n \t\t\t\t void (*notifier)(struct ncsi_dev *nd));\n int ncsi_start_dev(struct ncsi_dev *nd);\ndiff --git a/net/ncsi/internal.h b/net/ncsi/internal.h\nindex 1308a56f2591..af3d636534ef 100644\n--- a/net/ncsi/internal.h\n+++ b/net/ncsi/internal.h\n@@ -180,6 +180,7 @@ struct ncsi_channel {\n #define NCSI_CHANNEL_INACTIVE\t\t1\n #define NCSI_CHANNEL_ACTIVE\t\t2\n #define NCSI_CHANNEL_INVISIBLE\t\t3\n+\tbool reconfigure_needed;\n \tspinlock_t lock;\t/* Protect filters etc */\n \tstruct ncsi_package *package;\n \tstruct ncsi_channel_version version;\n@@ -235,6 +236,9 @@ enum {\n \tncsi_dev_state_probe_dp,\n \tncsi_dev_state_config_sp\t= 0x0301,\n \tncsi_dev_state_config_cis,\n+\tncsi_dev_state_config_clear_vids,\n+\tncsi_dev_state_config_svf,\n+\tncsi_dev_state_config_ev,\n \tncsi_dev_state_config_sma,\n \tncsi_dev_state_config_ebf,\n #if IS_ENABLED(CONFIG_IPV6)\n@@ -253,6 +257,12 @@ enum {\n \tncsi_dev_state_suspend_done\n };\n \n+struct vlan_vid {\n+\tstruct list_head list;\n+\t__be16 proto;\n+\tu16 vid;\n+};\n+\n struct ncsi_dev_priv {\n \tstruct ncsi_dev ndev; /* Associated NCSI device */\n \tunsigned int flags; /* NCSI device flags */\n@@ -276,6 +286,7 @@ struct ncsi_dev_priv {\n \tstruct work_struct work; /* For channel management */\n \tstruct packet_type ptype; /* NCSI packet Rx handler */\n \tstruct list_head node; /* Form NCSI device list */\n+\tstruct list_head vlan_vids; /* List of active VLAN IDs */\n };\n \n struct ncsi_cmd_arg {\ndiff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c\nindex a3bd5fa8ad09..11904b3b702d 100644\n--- a/net/ncsi/ncsi-manage.c\n+++ b/net/ncsi/ncsi-manage.c\n@@ -38,6 +38,25 @@ static inline int ncsi_filter_size(int table)\n \treturn sizes[table];\n }\n \n+u32 *ncsi_get_filter(struct ncsi_channel *nc, int table, int index)\n+{\n+\tstruct ncsi_channel_filter *ncf;\n+\tint size;\n+\n+\tncf = nc->filters[table];\n+\tif (!ncf)\n+\t\treturn NULL;\n+\n+\tsize = ncsi_filter_size(table);\n+\tif (size < 0)\n+\t\treturn NULL;\n+\n+\treturn ncf->data + size * index;\n+}\n+\n+/* Find the first active filter in a filter table that matches the given\n+ * data parameter. If data is NULL, this returns the first active filter.\n+ */\n int ncsi_find_filter(struct ncsi_channel *nc, int table, void *data)\n {\n \tstruct ncsi_channel_filter *ncf;\n@@ -58,7 +77,7 @@ int ncsi_find_filter(struct ncsi_channel *nc, int table, void *data)\n \tindex = -1;\n \twhile ((index = find_next_bit(bitmap, ncf->total, index + 1))\n \t < ncf->total) {\n-\t\tif (!memcmp(ncf->data + size * index, data, size)) {\n+\t\tif (!data || !memcmp(ncf->data + size * index, data, size)) {\n \t\t\tspin_unlock_irqrestore(&nc->lock, flags);\n \t\t\treturn index;\n \t\t}\n@@ -639,6 +658,95 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)\n \tnd->state = ncsi_dev_state_functional;\n }\n \n+/* Check the VLAN filter bitmap for a set filter, and construct a\n+ * \"Set VLAN Filter - Disable\" packet if found.\n+ */\n+static int clear_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,\n+\t\t\t struct ncsi_cmd_arg *nca)\n+{\n+\tint index;\n+\tu32 *data;\n+\tu16 vid;\n+\n+\tindex = ncsi_find_filter(nc, NCSI_FILTER_VLAN, NULL);\n+\tif (index < 0) {\n+\t\t/* Filter table empty */\n+\t\treturn -1;\n+\t}\n+\n+\tdata = ncsi_get_filter(nc, NCSI_FILTER_VLAN, index);\n+\tif (!data) {\n+\t\tnetdev_err(ndp->ndev.dev,\n+\t\t\t \"ncsi: failed to retrieve filter %d\\n\", index);\n+\t\t/* Set the VLAN id to 0 - this will still disable the entry in\n+\t\t * the filter table, but we won't know what it was.\n+\t\t */\n+\t\tvid = 0;\n+\t} else {\n+\t\tvid = *(u16 *)data;\n+\t}\n+\n+\tnetdev_printk(KERN_DEBUG, ndp->ndev.dev,\n+\t\t \"ncsi: removed vlan tag %u at index %d\\n\",\n+\t\t vid, index + 1);\n+\tncsi_remove_filter(nc, NCSI_FILTER_VLAN, index);\n+\n+\tnca->type = NCSI_PKT_CMD_SVF;\n+\tnca->words[1] = vid;\n+\t/* HW filter index starts at 1 */\n+\tnca->bytes[6] = index + 1;\n+\tnca->bytes[7] = 0x00;\n+\treturn 0;\n+}\n+\n+/* Find an outstanding VLAN tag and constuct a \"Set VLAN Filter - Enable\"\n+ * packet.\n+ */\n+static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,\n+\t\t struct ncsi_cmd_arg *nca)\n+{\n+\tstruct vlan_vid *vlan = NULL;\n+\tint index = 0;\n+\n+\tlist_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {\n+\t\tindex = ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan->vid);\n+\t\tif (index < 0) {\n+\t\t\t/* New tag to add */\n+\t\t\tnetdev_printk(KERN_DEBUG, ndp->ndev.dev,\n+\t\t\t\t \"ncsi: new vlan id to set: %u\\n\",\n+\t\t\t\t vlan->vid);\n+\t\t\tbreak;\n+\t\t}\n+\t\tnetdev_printk(KERN_DEBUG, ndp->ndev.dev,\n+\t\t\t \"vid %u already at filter pos %d\\n\",\n+\t\t\t vlan->vid, index);\n+\t}\n+\n+\tif (!vlan || index >= 0) {\n+\t\tnetdev_printk(KERN_DEBUG, ndp->ndev.dev,\n+\t\t\t \"no vlan ids left to set\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tindex = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan->vid);\n+\tif (index < 0) {\n+\t\tnetdev_err(ndp->ndev.dev,\n+\t\t\t \"Failed to add new VLAN tag, error %d\\n\", index);\n+\t\treturn -1;\n+\t}\n+\n+\tnetdev_printk(KERN_DEBUG, ndp->ndev.dev,\n+\t\t \"ncsi: set vid %u in packet, index %u\\n\",\n+\t\t vlan->vid, index + 1);\n+\tnca->type = NCSI_PKT_CMD_SVF;\n+\tnca->words[1] = vlan->vid;\n+\t/* HW filter index starts at 1 */\n+\tnca->bytes[6] = index + 1;\n+\tnca->bytes[7] = 0x01;\n+\n+\treturn 0;\n+}\n+\n static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)\n {\n \tstruct ncsi_dev *nd = &ndp->ndev;\n@@ -683,8 +791,11 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)\n \t\tif (ret)\n \t\t\tgoto error;\n \n-\t\tnd->state = ncsi_dev_state_config_sma;\n+\t\tnd->state = ncsi_dev_state_config_clear_vids;\n \t\tbreak;\n+\tcase ncsi_dev_state_config_clear_vids:\n+\tcase ncsi_dev_state_config_svf:\n+\tcase ncsi_dev_state_config_ev:\n \tcase ncsi_dev_state_config_sma:\n \tcase ncsi_dev_state_config_ebf:\n #if IS_ENABLED(CONFIG_IPV6)\n@@ -699,11 +810,40 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)\n \t\tnca.package = np->id;\n \t\tnca.channel = nc->id;\n \n+\t\t/* Clear any active filters on the channel before setting */\n+\t\tif (nd->state == ncsi_dev_state_config_clear_vids) {\n+\t\t\tret = clear_one_vid(ndp, nc, &nca);\n+\t\t\tif (ret) {\n+\t\t\t\tnd->state = ncsi_dev_state_config_svf;\n+\t\t\t\tschedule_work(&ndp->work);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\t/* Repeat */\n+\t\t\tnd->state = ncsi_dev_state_config_clear_vids;\n+\t\t/* Add known VLAN tags to the filter */\n+\t\t} else if (nd->state == ncsi_dev_state_config_svf) {\n+\t\t\tret = set_one_vid(ndp, nc, &nca);\n+\t\t\tif (ret) {\n+\t\t\t\tnd->state = ncsi_dev_state_config_ev;\n+\t\t\t\tschedule_work(&ndp->work);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\t/* Repeat */\n+\t\t\tnd->state = ncsi_dev_state_config_svf;\n+\t\t/* Enable/Disable the VLAN filter */\n+\t\t} else if (nd->state == ncsi_dev_state_config_ev) {\n+\t\t\tif (list_empty(&ndp->vlan_vids)) {\n+\t\t\t\tnca.type = NCSI_PKT_CMD_DV;\n+\t\t\t} else {\n+\t\t\t\tnca.type = NCSI_PKT_CMD_EV;\n+\t\t\t\tnca.bytes[3] = NCSI_CAP_VLAN_NO;\n+\t\t\t}\n+\t\t\tnd->state = ncsi_dev_state_config_sma;\n+\t\t} else if (nd->state == ncsi_dev_state_config_sma) {\n \t\t/* Use first entry in unicast filter table. Note that\n \t\t * the MAC filter table starts from entry 1 instead of\n \t\t * 0.\n \t\t */\n-\t\tif (nd->state == ncsi_dev_state_config_sma) {\n \t\t\tnca.type = NCSI_PKT_CMD_SMA;\n \t\t\tfor (index = 0; index < 6; index++)\n \t\t\t\tnca.bytes[index] = dev->dev_addr[index];\n@@ -751,6 +891,25 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)\n \t\tbreak;\n \tcase ncsi_dev_state_config_done:\n \t\tspin_lock_irqsave(&nc->lock, flags);\n+\t\tif (nc->reconfigure_needed) {\n+\t\t\t/* This channel's configuration has been updated\n+\t\t\t * part-way during the config state - start the\n+\t\t\t * channel configuration over\n+\t\t\t */\n+\t\t\tnc->reconfigure_needed = false;\n+\t\t\tnc->state = NCSI_CHANNEL_INACTIVE;\n+\t\t\tspin_unlock_irqrestore(&nc->lock, flags);\n+\n+\t\t\tspin_lock_irqsave(&ndp->lock, flags);\n+\t\t\tlist_add_tail_rcu(&nc->link, &ndp->channel_queue);\n+\t\t\tspin_unlock_irqrestore(&ndp->lock, flags);\n+\n+\t\t\tnetdev_printk(KERN_DEBUG, dev,\n+\t\t\t\t \"Dirty NCSI channel state reset\\n\");\n+\t\t\tncsi_process_next_channel(ndp);\n+\t\t\tbreak;\n+\t\t}\n+\n \t\tif (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {\n \t\t\thot_nc = nc;\n \t\t\tnc->state = NCSI_CHANNEL_ACTIVE;\n@@ -1191,6 +1350,148 @@ static struct notifier_block ncsi_inet6addr_notifier = {\n };\n #endif /* CONFIG_IPV6 */\n \n+static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)\n+{\n+\tstruct ncsi_dev *nd = &ndp->ndev;\n+\tstruct ncsi_channel *nc;\n+\tstruct ncsi_package *np;\n+\tunsigned long flags;\n+\tunsigned int n = 0;\n+\n+\tNCSI_FOR_EACH_PACKAGE(ndp, np) {\n+\t\tNCSI_FOR_EACH_CHANNEL(np, nc) {\n+\t\t\tspin_lock_irqsave(&nc->lock, flags);\n+\n+\t\t\t/* Channels may be busy, mark dirty instead of\n+\t\t\t * kicking if;\n+\t\t\t * a) not ACTIVE (configured)\n+\t\t\t * b) in the channel_queue (to be configured)\n+\t\t\t * c) it's ndev is in the config state\n+\t\t\t */\n+\t\t\tif (nc->state != NCSI_CHANNEL_ACTIVE) {\n+\t\t\t\tif ((ndp->ndev.state & 0xff00) ==\n+\t\t\t\t\t\tncsi_dev_state_config ||\n+\t\t\t\t\t\t!list_empty(&nc->link)) {\n+\t\t\t\t\tnetdev_printk(KERN_DEBUG, nd->dev,\n+\t\t\t\t\t\t \"ncsi: channel %p marked dirty\\n\",\n+\t\t\t\t\t\t nc);\n+\t\t\t\t\tnc->reconfigure_needed = true;\n+\t\t\t\t}\n+\t\t\t\tspin_unlock_irqrestore(&nc->lock, flags);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tspin_unlock_irqrestore(&nc->lock, flags);\n+\n+\t\t\tncsi_stop_channel_monitor(nc);\n+\t\t\tspin_lock_irqsave(&nc->lock, flags);\n+\t\t\tnc->state = NCSI_CHANNEL_INACTIVE;\n+\t\t\tspin_unlock_irqrestore(&nc->lock, flags);\n+\n+\t\t\tspin_lock_irqsave(&ndp->lock, flags);\n+\t\t\tlist_add_tail_rcu(&nc->link, &ndp->channel_queue);\n+\t\t\tspin_unlock_irqrestore(&ndp->lock, flags);\n+\n+\t\t\tnetdev_printk(KERN_DEBUG, nd->dev,\n+\t\t\t\t \"ncsi: kicked channel %p\\n\", nc);\n+\t\t\tn++;\n+\t\t}\n+\t}\n+\n+\treturn n;\n+}\n+\n+int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)\n+{\n+\tstruct ncsi_channel_filter *ncf;\n+\tstruct ncsi_dev_priv *ndp;\n+\tunsigned int n_vids = 0;\n+\tstruct vlan_vid *vlan;\n+\tstruct ncsi_dev *nd;\n+\tbool found = false;\n+\n+\tif (vid == 0)\n+\t\treturn 0;\n+\n+\tnd = ncsi_find_dev(dev);\n+\tif (!nd) {\n+\t\tnetdev_warn(dev, \"ncsi: No net_device?\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tndp = TO_NCSI_DEV_PRIV(nd);\n+\tncf = ndp->hot_channel->filters[NCSI_FILTER_VLAN];\n+\n+\t/* Add the VLAN id to our internal list */\n+\tlist_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {\n+\t\tn_vids++;\n+\t\tif (vlan->vid == vid) {\n+\t\t\tnetdev_printk(KERN_DEBUG, dev,\n+\t\t\t\t \"vid %u already registered\\n\", vid);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\tif (n_vids >= ncf->total) {\n+\t\tnetdev_info(dev,\n+\t\t\t \"NCSI Channel supports up to %u VLAN tags but %u are already set\\n\",\n+\t\t\t ncf->total, n_vids);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tvlan = kzalloc(sizeof(*vlan), GFP_KERNEL);\n+\tif (!vlan)\n+\t\treturn -ENOMEM;\n+\n+\tvlan->proto = proto;\n+\tvlan->vid = vid;\n+\tlist_add_rcu(&vlan->list, &ndp->vlan_vids);\n+\n+\tnetdev_printk(KERN_DEBUG, dev, \"Added new vid %u\\n\", vid);\n+\n+\tfound = ncsi_kick_channels(ndp) != 0;\n+\n+\treturn found ? ncsi_process_next_channel(ndp) : 0;\n+}\n+\n+int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)\n+{\n+\tstruct vlan_vid *vlan, *tmp;\n+\tstruct ncsi_dev_priv *ndp;\n+\tstruct ncsi_dev *nd;\n+\tbool found = false;\n+\n+\tif (vid == 0)\n+\t\treturn 0;\n+\n+\tnd = ncsi_find_dev(dev);\n+\tif (!nd) {\n+\t\tnetdev_warn(dev, \"ncsi: no net_device?\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tndp = TO_NCSI_DEV_PRIV(nd);\n+\n+\t/* Remove the VLAN id from our internal list */\n+\tlist_for_each_entry_safe(vlan, tmp, &ndp->vlan_vids, list)\n+\t\tif (vlan->vid == vid) {\n+\t\t\tnetdev_printk(KERN_DEBUG, dev,\n+\t\t\t\t \"vid %u found, removing\\n\", vid);\n+\t\t\tlist_del_rcu(&vlan->list);\n+\t\t\tfound = true;\n+\t\t\tkfree(vlan);\n+\t\t}\n+\n+\tif (!found) {\n+\t\tnetdev_err(dev, \"ncsi: vid %u wasn't registered!\\n\", vid);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfound = ncsi_kick_channels(ndp) != 0;\n+\n+\treturn found ? ncsi_process_next_channel(ndp) : 0;\n+}\n+\n struct ncsi_dev *ncsi_register_dev(struct net_device *dev,\n \t\t\t\t void (*handler)(struct ncsi_dev *ndev))\n {\n@@ -1215,6 +1516,7 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,\n \tnd->handler = handler;\n \tndp->pending_req_num = 0;\n \tINIT_LIST_HEAD(&ndp->channel_queue);\n+\tINIT_LIST_HEAD(&ndp->vlan_vids);\n \tINIT_WORK(&ndp->work, ncsi_dev_work);\n \n \t/* Initialize private NCSI device */\ndiff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c\nindex c1a191d790e2..265b9a892d41 100644\n--- a/net/ncsi/ncsi-rsp.c\n+++ b/net/ncsi/ncsi-rsp.c\n@@ -694,7 +694,14 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)\n \n \t\tncf->index = i;\n \t\tncf->total = cnt;\n-\t\tncf->bitmap = 0x0ul;\n+\t\tif (i == NCSI_FILTER_VLAN) {\n+\t\t\t/* Set VLAN filters active so they are cleared in\n+\t\t\t * first configuration state\n+\t\t\t */\n+\t\t\tncf->bitmap = U64_MAX;\n+\t\t} else {\n+\t\t\tncf->bitmap = 0x0ul;\n+\t\t}\n \t\tnc->filters[i] = ncf;\n \t}\n \n", "prefixes": [ "net-next", "v3", "2/3" ] }