get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 806379,
    "url": "http://patchwork.ozlabs.org/api/patches/806379/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openbmc/patch/20170828061843.24349-3-sam@mendozajonas.com/",
    "project": {
        "id": 56,
        "url": "http://patchwork.ozlabs.org/api/projects/56/?format=api",
        "name": "OpenBMC development",
        "link_name": "openbmc",
        "list_id": "openbmc.lists.ozlabs.org",
        "list_email": "openbmc@lists.ozlabs.org",
        "web_url": "http://github.com/openbmc/",
        "scm_url": "",
        "webscm_url": "",
        "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": "not-applicable",
    "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": null,
    "mbox": "http://patchwork.ozlabs.org/project/openbmc/patch/20170828061843.24349-3-sam@mendozajonas.com/mbox/",
    "series": [
        {
            "id": 79,
            "url": "http://patchwork.ozlabs.org/api/series/79/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openbmc/list/?series=79",
            "date": "2017-08-28T06:18:40",
            "name": "NCSI VLAN Filtering Support",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/79/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/806379/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/806379/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "openbmc@lists.ozlabs.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "openbmc@lists.ozlabs.org"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xghTF6Vg0z9sNq\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 28 Aug 2017 16:20:17 +1000 (AEST)",
            "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xghTF4fPyzDqFv\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 28 Aug 2017 16:20:17 +1000 (AEST)",
            "from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com\n\t[66.111.4.26])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xghRs4L8JzDq8f\n\tfor <openbmc@lists.ozlabs.org>; Mon, 28 Aug 2017 16:19:05 +1000 (AEST)",
            "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)"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=\"nbhyz3oo\"; \n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=messagingengine.com\n\theader.i=@messagingengine.com header.b=\"oeFt3/dY\"; \n\tdkim-atps=neutral",
            "lists.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=mendozajonas.com header.i=@mendozajonas.com\n\theader.b=\"nbhyz3oo\"; \n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=messagingengine.com\n\theader.i=@messagingengine.com header.b=\"oeFt3/dY\"; \n\tdkim-atps=neutral",
            "lists.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\n\theader.b=\"oeFt3/dY\"; dkim-atps=neutral"
        ],
        "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>",
        "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>",
        "X-BeenThere": "openbmc@lists.ozlabs.org",
        "X-Mailman-Version": "2.1.23",
        "Precedence": "list",
        "List-Id": "Development list for OpenBMC <openbmc.lists.ozlabs.org>",
        "List-Unsubscribe": "<https://lists.ozlabs.org/options/openbmc>,\n\t<mailto:openbmc-request@lists.ozlabs.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.ozlabs.org/pipermail/openbmc/>",
        "List-Post": "<mailto:openbmc@lists.ozlabs.org>",
        "List-Help": "<mailto:openbmc-request@lists.ozlabs.org?subject=help>",
        "List-Subscribe": "<https://lists.ozlabs.org/listinfo/openbmc>,\n\t<mailto:openbmc-request@lists.ozlabs.org?subject=subscribe>",
        "Cc": "Samuel Mendoza-Jonas <sam@mendozajonas.com>,\n\tGavin Shan <gwshan@linux.vnet.ibm.com>",
        "Errors-To": "openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org",
        "Sender": "\"openbmc\"\n\t<openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.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"
    ]
}