get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 802474,
    "url": "http://patchwork.ozlabs.org/api/patches/802474/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/150296406010.16167.17659779723026390788.stgit@anamdev.jf.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": "<150296406010.16167.17659779723026390788.stgit@anamdev.jf.intel.com>",
    "list_archive_url": null,
    "date": "2017-08-17T10:01:00",
    "name": "[v2,3/6,net-next] net: i40e: Add infrastructure for queue channel support with the TCs and queue configurations offloaded via mqprio scheduler",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "f5e4d716fc723f669efef83324f225bac4d2362d",
    "submitter": {
        "id": 68504,
        "url": "http://patchwork.ozlabs.org/api/people/68504/?format=api",
        "name": "Nambiar, Amritha",
        "email": "amritha.nambiar@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/150296406010.16167.17659779723026390788.stgit@anamdev.jf.intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/802474/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/802474/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@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"
        ],
        "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.133; helo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\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 3xY1wJ0JLGz9sRV\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 17 Aug 2017 20:02:07 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 1BB168A128;\n\tThu, 17 Aug 2017 10:02:06 +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 axyLwzirB7tl; Thu, 17 Aug 2017 10:02:03 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 875238A127;\n\tThu, 17 Aug 2017 10:02:03 +0000 (UTC)",
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id 5EADD1C072D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 17 Aug 2017 10:02:02 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 57A5E88089\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 17 Aug 2017 10:02:02 +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 2MLlMrDStOLC for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 17 Aug 2017 10:01:59 +0000 (UTC)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby fraxinus.osuosl.org (Postfix) with ESMTPS id 9A5F788084\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 17 Aug 2017 10:01:59 +0000 (UTC)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t17 Aug 2017 03:01:51 -0700",
            "from anamdev.jf.intel.com ([10.166.29.110])\n\tby orsmga005.jf.intel.com with ESMTP; 17 Aug 2017 03:01:50 -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.41,387,1498546800\"; d=\"scan'208\";a=\"138645084\"",
        "From": "Amritha Nambiar <amritha.nambiar@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org, jeffrey.t.kirsher@intel.com",
        "Date": "Thu, 17 Aug 2017 03:01:00 -0700",
        "Message-ID": "<150296406010.16167.17659779723026390788.stgit@anamdev.jf.intel.com>",
        "In-Reply-To": "<150296373549.16167.14331445560838257351.stgit@anamdev.jf.intel.com>",
        "References": "<150296373549.16167.14331445560838257351.stgit@anamdev.jf.intel.com>",
        "User-Agent": "StGit/0.17.1-dirty",
        "MIME-Version": "1.0",
        "Subject": "[Intel-wired-lan] [PATCH v2 3/6] [net-next]net: i40e: Add\n\tinfrastructure for queue channel support with the TCs and queue\n\tconfigurations offloaded via mqprio scheduler",
        "X-BeenThere": "intel-wired-lan@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.osuosl.org>",
        "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>",
        "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"
    },
    "content": "This patch sets up the infrastructure for offloading TCs and\nqueue configurations to the hardware by creating HW channels(VSI).\nA new channel is created for each of the traffic class\nconfiguration offloaded via mqprio framework except for the first TC\n(TC0). TC0 for the main VSI is also reconfigured as per user provided\nqueue parameters. Queue counts that are not power-of-2 are handled by\nreconfiguring RSS by reprogramming LUTs using the queue count value.\nThis patch also handles configuring the TX rings for the channels,\nsetting up the RX queue map for channel.\n\nAlso, the channels so created are removed and all the queue\nconfiguration is set to default when the qdisc is detached from the\nroot of the device.\n\nSigned-off-by: Amritha Nambiar <amritha.nambiar@intel.com>\nSigned-off-by: Kiran Patil <kiran.patil@intel.com>\n---\n drivers/net/ethernet/intel/i40e/i40e.h      |   33 +\n drivers/net/ethernet/intel/i40e/i40e_main.c |  747 +++++++++++++++++++++++++++\n drivers/net/ethernet/intel/i40e/i40e_txrx.h |    2 \n 3 files changed, 773 insertions(+), 9 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 0e53838..e259a67 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -87,6 +87,7 @@\n #define I40E_AQ_LEN\t\t\t256\n #define I40E_AQ_WORK_LIMIT\t\t66 /* max number of VFs + a little */\n #define I40E_MAX_USER_PRIORITY\t\t8\n+#define I40E_MAX_QUEUES_PER_CH\t\t64\n #define I40E_DEFAULT_TRAFFIC_CLASS\tBIT(0)\n #define I40E_DEFAULT_MSG_ENABLE\t\t4\n #define I40E_QUEUE_WAIT_RETRY_LIMIT\t10\n@@ -340,6 +341,23 @@ struct i40e_flex_pit {\n \tu8 pit_index;\n };\n \n+struct i40e_channel {\n+\tstruct list_head list;\n+\tbool initialized;\n+\tu8 type;\n+\tu16 vsi_number; /* Assigned VSI number from AQ 'Add VSI' response */\n+\tu16 stat_counter_idx;\n+\tu16 base_queue;\n+\tu16 num_queue_pairs; /* Requested by user */\n+\tu16 seid;\n+\n+\tu8 enabled_tc;\n+\tstruct i40e_aqc_vsi_properties_data info;\n+\n+\t/* track this channel belongs to which VSI */\n+\tstruct i40e_vsi *parent_vsi;\n+};\n+\n /* struct that defines the Ethernet device */\n struct i40e_pf {\n \tstruct pci_dev *pdev;\n@@ -455,6 +473,7 @@ struct i40e_pf {\n #define I40E_FLAG_CLIENT_L2_CHANGE\t\tBIT_ULL(25)\n #define I40E_FLAG_CLIENT_RESET\t\t\tBIT_ULL(26)\n #define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED\tBIT_ULL(27)\n+#define I40E_FLAG_TC_MQPRIO\t\t\tBIT_ULL(28)\n \n \tstruct i40e_client_instance *cinst;\n \tbool stat_offsets_loaded;\n@@ -535,6 +554,8 @@ struct i40e_pf {\n \tu32 ioremap_len;\n \tu32 fd_inv;\n \tu16 phy_led_val;\n+\n+\tu16 override_q_count;\n };\n \n /**\n@@ -699,6 +720,16 @@ struct i40e_vsi {\n \tbool current_isup;\t/* Sync 'link up' logging */\n \tenum i40e_aq_link_speed current_speed;\t/* Sync link speed logging */\n \n+\t/* channel specific fields */\n+\tu16 cnt_q_avail; /* num of queues available for channel usage */\n+\tu16 orig_rss_size;\n+\tu16 current_rss_size;\n+\n+\t/* keeps track of next_base_queue to be used for channel setup */\n+\tatomic_t next_base_queue;\n+\n+\tstruct list_head ch_list;\n+\n \tvoid *priv;\t/* client driver data reference. */\n \n \t/* VSI specific handlers */\n@@ -1006,4 +1037,6 @@ static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)\n {\n \treturn !!vsi->xdp_prog;\n }\n+\n+int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);\n #endif /* _I40E_H_ */\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 9392c5a..64769cb 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -2887,7 +2887,7 @@ static void i40e_config_xps_tx_ring(struct i40e_ring *ring)\n {\n \tstruct i40e_vsi *vsi = ring->vsi;\n \n-\tif (!ring->q_vector || !ring->netdev)\n+\tif (!ring->q_vector || !ring->netdev || ring->ch)\n \t\treturn;\n \n \tif ((vsi->tc_config.numtc <= 1) &&\n@@ -2954,7 +2954,14 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)\n \t * initialization. This has to be done regardless of\n \t * DCB as by default everything is mapped to TC0.\n \t */\n-\ttx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[ring->dcb_tc]);\n+\n+\tif (ring->ch)\n+\t\ttx_ctx.rdylist =\n+\t\t\tle16_to_cpu(ring->ch->info.qs_handle[ring->dcb_tc]);\n+\n+\telse\n+\t\ttx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[ring->dcb_tc]);\n+\n \ttx_ctx.rdylist_act = 0;\n \n \t/* clear the context in the HMC */\n@@ -2976,12 +2983,23 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)\n \t}\n \n \t/* Now associate this queue with this PCI function */\n-\tif (vsi->type == I40E_VSI_VMDQ2) {\n-\t\tqtx_ctl = I40E_QTX_CTL_VM_QUEUE;\n-\t\tqtx_ctl |= ((vsi->id) << I40E_QTX_CTL_VFVM_INDX_SHIFT) &\n-\t\t\t   I40E_QTX_CTL_VFVM_INDX_MASK;\n+\tif (ring->ch) {\n+\t\tif (ring->ch->type == I40E_VSI_VMDQ2)\n+\t\t\tqtx_ctl = I40E_QTX_CTL_VM_QUEUE;\n+\t\telse\n+\t\t\treturn -EINVAL;\n+\n+\t\tqtx_ctl |= (ring->ch->vsi_number <<\n+\t\t\t    I40E_QTX_CTL_VFVM_INDX_SHIFT) &\n+\t\t\t    I40E_QTX_CTL_VFVM_INDX_MASK;\n \t} else {\n-\t\tqtx_ctl = I40E_QTX_CTL_PF_QUEUE;\n+\t\tif (vsi->type == I40E_VSI_VMDQ2) {\n+\t\t\tqtx_ctl = I40E_QTX_CTL_VM_QUEUE;\n+\t\t\tqtx_ctl |= ((vsi->id) << I40E_QTX_CTL_VFVM_INDX_SHIFT) &\n+\t\t\t\t    I40E_QTX_CTL_VFVM_INDX_MASK;\n+\t\t} else {\n+\t\t\tqtx_ctl = I40E_QTX_CTL_PF_QUEUE;\n+\t\t}\n \t}\n \n \tqtx_ctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) &\n@@ -5168,6 +5186,672 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n }\n \n /**\n+ * i40e_remove_queue_channels - Remove queue channels for the TCs\n+ * @vsi: VSI to be configured\n+ *\n+ * Remove queue channels for the TCs\n+ **/\n+static void i40e_remove_queue_channels(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tint ret, i;\n+\n+\t/* Reset rss size that was stored when reconfiguring rss for\n+\t * channel VSIs with non-power-of-2 queue count.\n+\t */\n+\tvsi->current_rss_size = 0;\n+\n+\t/* perform cleanup for channels if they exist */\n+\tif (list_empty(&vsi->ch_list))\n+\t\treturn;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {\n+\t\tstruct i40e_vsi *p_vsi;\n+\n+\t\tlist_del(&ch->list);\n+\t\tp_vsi = ch->parent_vsi;\n+\t\tif (!p_vsi || !ch->initialized) {\n+\t\t\tkfree(ch);\n+\t\t\tcontinue;\n+\t\t}\n+\t\t/* Reset queue contexts */\n+\t\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\t\tstruct i40e_ring *tx_ring, *rx_ring;\n+\t\t\tu16 pf_q;\n+\n+\t\t\tpf_q = ch->base_queue + i;\n+\t\t\ttx_ring = vsi->tx_rings[pf_q];\n+\t\t\ttx_ring->ch = NULL;\n+\n+\t\t\trx_ring = vsi->rx_rings[pf_q];\n+\t\t\trx_ring->ch = NULL;\n+\t\t}\n+\n+\t\t/* delete VSI from FW */\n+\t\tret = i40e_aq_delete_element(&vsi->back->hw, ch->seid,\n+\t\t\t\t\t     NULL);\n+\t\tif (ret)\n+\t\t\tdev_err(&vsi->back->pdev->dev,\n+\t\t\t\t\"unable to remove channel (%d) for parent VSI(%d)\\n\",\n+\t\t\t\tch->seid, p_vsi->seid);\n+\t\tkfree(ch);\n+\t}\n+\tINIT_LIST_HEAD(&vsi->ch_list);\n+}\n+\n+/**\n+ * i40e_is_any_channel - channel exist or not\n+ * @vsi: ptr to VSI to which channels are associated with\n+ *\n+ * Returns true or false if channel(s) exist for associated VSI or not\n+ **/\n+static bool i40e_is_any_channel(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {\n+\t\tif (ch->initialized)\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+/**\n+ * i40e_get_max_queues_for_channel\n+ * @vsi: ptr to VSI to which channels are associated with\n+ *\n+ * Helper function which returns max value among the queue counts set on the\n+ * channels/TCs created.\n+ **/\n+static int i40e_get_max_queues_for_channel(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\tint max = 0;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {\n+\t\tif (!ch->initialized)\n+\t\t\tcontinue;\n+\t\tif (ch->num_queue_pairs > max)\n+\t\t\tmax = ch->num_queue_pairs;\n+\t}\n+\n+\treturn max;\n+}\n+\n+/**\n+ * i40e_validate_num_queues - validate num_queues w.r.t channel\n+ * @pf: ptr to PF device\n+ * @num_queues: number of queues\n+ * @vsi: the parent VSI\n+ * @reconfig_rss: indicates should the RSS be reconfigured or not\n+ *\n+ * This function validates number of queues in the context of new channel\n+ * which is being established and determines if RSS should be reconfigured\n+ * or not for parent VSI.\n+ **/\n+static int i40e_validate_num_queues(struct i40e_pf *pf, int num_queues,\n+\t\t\t\t    struct i40e_vsi *vsi, bool *reconfig_rss)\n+{\n+\tint max_ch_queues;\n+\n+\tif (!reconfig_rss)\n+\t\treturn -EINVAL;\n+\n+\t*reconfig_rss = false;\n+\n+\tif (num_queues > I40E_MAX_QUEUES_PER_CH) {\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"Failed to create VMDq VSI. User requested num_queues (%d) > I40E_MAX_QUEUES_PER_VSI (%u)\\n\",\n+\t\t\tnum_queues, I40E_MAX_QUEUES_PER_CH);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (vsi->current_rss_size) {\n+\t\tif (num_queues > vsi->current_rss_size) {\n+\t\t\tdev_dbg(&pf->pdev->dev,\n+\t\t\t\t\"Error: num_queues (%d) > vsi's current_size(%d)\\n\",\n+\t\t\t\tnum_queues, vsi->current_rss_size);\n+\t\t\treturn -EINVAL;\n+\t\t} else if ((num_queues < vsi->current_rss_size) &&\n+\t\t\t   (!is_power_of_2(num_queues))) {\n+\t\t\tdev_dbg(&pf->pdev->dev,\n+\t\t\t\t\"Error: num_queues (%d) < vsi's current_size(%d), but not power of 2\\n\",\n+\t\t\t\tnum_queues, vsi->current_rss_size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (!is_power_of_2(num_queues)) {\n+\t\t/* Find the max num_queues configures for channel if channel\n+\t\t * exist.\n+\t\t * if channel exist, then enforce 'num_queues' to be more than\n+\t\t * max ever num_queues configured for channel.\n+\t\t */\n+\t\tmax_ch_queues = i40e_get_max_queues_for_channel(vsi);\n+\t\tif (num_queues < max_ch_queues) {\n+\t\t\tdev_dbg(&pf->pdev->dev,\n+\t\t\t\t\"Error: num_queues (%d) > main_vsi's current_size(%d)\\n\",\n+\t\t\t\tnum_queues, vsi->current_rss_size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\t*reconfig_rss = true;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * i40e_vsi_reconfig_rss - reconfig RSS based on specified rss_size\n+ * @vsi: the VSI being setup\n+ * @rss_size: size of RSS, accordingly LUT gets reprogrammed\n+ *\n+ * This function reconfigures RSS by reprogramming LUTs using 'rss_size'\n+ **/\n+static int i40e_vsi_reconfig_rss(struct i40e_vsi *vsi, u16 rss_size)\n+{\n+\tstruct i40e_pf *pf = vsi->back;\n+\tu8 seed[I40E_HKEY_ARRAY_SIZE];\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tint local_rss_size;\n+\tu8 *lut;\n+\tint ret;\n+\n+\tif (!vsi->rss_size)\n+\t\treturn -EINVAL;\n+\n+\tif (rss_size > vsi->rss_size)\n+\t\treturn -EINVAL;\n+\n+\tlocal_rss_size = min_t(int, vsi->rss_size, rss_size);\n+\tlut = kzalloc(vsi->rss_table_size, GFP_KERNEL);\n+\tif (!lut)\n+\t\treturn -ENOMEM;\n+\n+\t/* Ignoring user configured lut if there is one */\n+\ti40e_fill_rss_lut(pf, lut, vsi->rss_table_size, local_rss_size);\n+\n+\t/* Use user configured hash key if there is one, otherwise\n+\t * use default.\n+\t */\n+\tif (vsi->rss_hkey_user)\n+\t\tmemcpy(seed, vsi->rss_hkey_user, I40E_HKEY_ARRAY_SIZE);\n+\telse\n+\t\tnetdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE);\n+\n+\tret = i40e_config_rss(vsi, seed, lut, vsi->rss_table_size);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"Cannot set RSS lut, err %s aq_err %s\\n\",\n+\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n+\t\tkfree(lut);\n+\t\treturn ret;\n+\t}\n+\tkfree(lut);\n+\n+\t/* Do the update w.r.t. storing rss_size */\n+\tif (!vsi->orig_rss_size)\n+\t\tvsi->orig_rss_size = vsi->rss_size;\n+\tvsi->current_rss_size = local_rss_size;\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_channel_setup_queue_map - Setup a channel queue map based on enabled_tc\n+ * @pf: ptr to PF device\n+ * @vsi: the VSI being setup\n+ * @ctxt: VSI context structure\n+ * @enabled_tc: Enabled TCs bitmap\n+ * @ch: ptr to channel structure\n+ *\n+ * Setup queue map based on enabled_tc for specific channel\n+ **/\n+static void i40e_channel_setup_queue_map(struct i40e_pf *pf,\n+\t\t\t\t\t struct i40e_vsi_context *ctxt,\n+\t\t\t\t\t u8 enabled_tc, struct i40e_channel *ch)\n+{\n+\tu16 qcount, num_tc_qps, qmap;\n+\tint pow, num_qps;\n+\tu16 sections = 0;\n+\t/* At least TC0 is enabled in case of non-DCB case, non-MQPRIO */\n+\tu16 numtc = 1;\n+\tu8 offset = 0;\n+\n+\tsections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;\n+\tsections |= I40E_AQ_VSI_PROP_SCHED_VALID;\n+\n+\tif (pf->flags & I40E_FLAG_MSIX_ENABLED) {\n+\t\tqcount = min_t(int, ch->num_queue_pairs,\n+\t\t\t       pf->num_lan_msix);\n+\t\tch->num_queue_pairs = qcount;\n+\t} else {\n+\t\tqcount = 1;\n+\t}\n+\n+\t/* find num of qps per traffic class */\n+\tnum_tc_qps = qcount / numtc;\n+\tnum_tc_qps = min_t(int, num_tc_qps, i40e_pf_get_max_q_per_tc(pf));\n+\tnum_qps = qcount;\n+\n+\t/* find the next higher power-of-2 of num queue pairs */\n+\tpow = ilog2(num_qps);\n+\tif (!is_power_of_2(num_qps))\n+\t\tpow++;\n+\n+\tqmap = (offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |\n+\t\t(pow << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT);\n+\n+\t/* Setup queue TC[0].qmap for given VSI context */\n+\tctxt->info.tc_mapping[0] = cpu_to_le16(qmap);\n+\n+\tctxt->info.up_enable_bits = enabled_tc;\n+\tctxt->info.mapping_flags |= cpu_to_le16(I40E_AQ_VSI_QUE_MAP_CONTIG);\n+\tctxt->info.queue_mapping[0] = cpu_to_le16(ch->base_queue);\n+\tctxt->info.valid_sections |= cpu_to_le16(sections);\n+}\n+\n+/**\n+ * i40e_add_channel - add a channel by adding VSI\n+ * @pf: ptr to PF device\n+ * @uplink_seid: underlying HW switching element (VEB) ID\n+ * @ch: ptr to channel structure\n+ *\n+ * Add a channel (VSI) using add_vsi and queue_map\n+ **/\n+static int i40e_add_channel(struct i40e_pf *pf, u16 uplink_seid,\n+\t\t\t    struct i40e_channel *ch)\n+{\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tstruct i40e_vsi_context ctxt;\n+\tu8 enabled_tc = 0x1; /* TC0 enabled */\n+\tint ret;\n+\n+\tif (ch->type != I40E_VSI_VMDQ2) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"add new vsi failed, ch->type %d\\n\", ch->type);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmemset(&ctxt, 0, sizeof(ctxt));\n+\tctxt.pf_num = hw->pf_id;\n+\tctxt.vf_num = 0;\n+\tctxt.uplink_seid = uplink_seid;\n+\tctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;\n+\tif (ch->type == I40E_VSI_VMDQ2)\n+\t\tctxt.flags = I40E_AQ_VSI_TYPE_VMDQ2;\n+\n+\tif (pf->flags & I40E_FLAG_VEB_MODE_ENABLED) {\n+\t\tctxt.info.valid_sections |=\n+\t\t     cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);\n+\t\tctxt.info.switch_id =\n+\t\t   cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);\n+\t}\n+\n+\t/* Set queue map for a given VSI context */\n+\ti40e_channel_setup_queue_map(pf, &ctxt, enabled_tc, ch);\n+\n+\t/* Now time to create VSI */\n+\tret = i40e_aq_add_vsi(hw, &ctxt, NULL);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"add new vsi failed, err %s aq_err %s\\n\",\n+\t\t\t i40e_stat_str(&pf->hw, ret),\n+\t\t\t i40e_aq_str(&pf->hw,\n+\t\t\t\t     pf->hw.aq.asq_last_status));\n+\t\treturn -ENOENT;\n+\t}\n+\n+\t/* Success, update channel */\n+\tch->enabled_tc = enabled_tc;\n+\tch->seid = ctxt.seid;\n+\tch->vsi_number = ctxt.vsi_number;\n+\tch->stat_counter_idx = cpu_to_le16(ctxt.info.stat_counter_idx);\n+\n+\t/* copy just the sections touched not the entire info\n+\t * since not all sections are valid as returned by\n+\t * update vsi params\n+\t */\n+\tch->info.mapping_flags = ctxt.info.mapping_flags;\n+\tmemcpy(&ch->info.queue_mapping,\n+\t       &ctxt.info.queue_mapping, sizeof(ctxt.info.queue_mapping));\n+\tmemcpy(&ch->info.tc_mapping, ctxt.info.tc_mapping,\n+\t       sizeof(ctxt.info.tc_mapping));\n+\n+\treturn 0;\n+}\n+\n+static int i40e_channel_config_bw(struct i40e_vsi *vsi, struct i40e_channel *ch,\n+\t\t\t\t  u8 *bw_share)\n+{\n+\tstruct i40e_aqc_configure_vsi_tc_bw_data bw_data;\n+\ti40e_status ret;\n+\tint i;\n+\n+\tbw_data.tc_valid_bits = ch->enabled_tc;\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)\n+\t\tbw_data.tc_bw_credits[i] = bw_share[i];\n+\n+\tret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, ch->seid,\n+\t\t\t\t       &bw_data, NULL);\n+\tif (ret) {\n+\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t \"Config VSI BW allocation per TC failed, aq_err: %d for new_vsi->seid %u\\n\",\n+\t\t\t vsi->back->hw.aq.asq_last_status, ch->seid);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)\n+\t\tch->info.qs_handle[i] = bw_data.qs_handles[i];\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * i40e_channel_config_tx_ring - config TX ring associated with new channel\n+ * @pf: ptr to PF device\n+ * @vsi: the VSI being setup\n+ * @ch: ptr to channel structure\n+ *\n+ * Configure TX rings associated with channel (VSI) since queues are being\n+ * from parent VSI.\n+ **/\n+static int i40e_channel_config_tx_ring(struct i40e_pf *pf,\n+\t\t\t\t       struct i40e_vsi *vsi,\n+\t\t\t\t       struct i40e_channel *ch)\n+{\n+\ti40e_status ret;\n+\tint i;\n+\tu8 bw_share[I40E_MAX_TRAFFIC_CLASS] = {0};\n+\n+\t/* Enable ETS TCs with equal BW Share for now across all VSIs */\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tif (ch->enabled_tc & BIT(i))\n+\t\t\tbw_share[i] = 1;\n+\t}\n+\n+\t/* configure BW for new VSI */\n+\tret = i40e_channel_config_bw(vsi, ch, bw_share);\n+\tif (ret) {\n+\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t \"Failed configuring TC map %d for channel (seid %u)\\n\",\n+\t\t\t ch->enabled_tc, ch->seid);\n+\t\treturn ret;\n+\t}\n+\n+\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\tstruct i40e_ring *tx_ring, *rx_ring;\n+\t\tu16 pf_q;\n+\n+\t\tpf_q = ch->base_queue + i;\n+\n+\t\t/* Get to TX ring ptr of main VSI, for re-setup TX queue\n+\t\t * context\n+\t\t */\n+\t\ttx_ring = vsi->tx_rings[pf_q];\n+\t\ttx_ring->ch = ch;\n+\n+\t\t/* Get the RX ring ptr */\n+\t\trx_ring = vsi->rx_rings[pf_q];\n+\t\trx_ring->ch = ch;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * i40e_setup_hw_channel - setup new channel\n+ * @pf: ptr to PF device\n+ * @vsi: the VSI being setup\n+ * @ch: ptr to channel structure\n+ * @uplink_seid: underlying HW switching element (VEB) ID\n+ * @type: type of channel to be created (VMDq2/VF)\n+ *\n+ * Setup new channel (VSI) based on specified type (VMDq2/VF)\n+ * and configures TX rings accordingly\n+ **/\n+static inline int i40e_setup_hw_channel(struct i40e_pf *pf,\n+\t\t\t\t\tstruct i40e_vsi *vsi,\n+\t\t\t\t\tstruct i40e_channel *ch,\n+\t\t\t\t\tu16 uplink_seid, u8 type)\n+{\n+\tstruct i40e_q_vector *q_vector;\n+\tint base_queue = 0;\n+\tint ret, i;\n+\n+\tch->initialized = false;\n+\tch->base_queue = atomic_read(&vsi->next_base_queue);\n+\tch->type = type;\n+\n+\t/* Proceed with creation of channel (VMDq2) VSI */\n+\tret = i40e_add_channel(pf, uplink_seid, ch);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"failed to add_channel using uplink_seid %u\\n\",\n+\t\t\t uplink_seid);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Mark the successful creation of channel */\n+\tch->initialized = true;\n+\n+\t/* Mark q_vectors indicating that they are part of newly created\n+\t * channel (VSI)\n+\t */\n+\tbase_queue = ch->base_queue;\n+\tfor (i = 0; i < ch->num_queue_pairs; i++) {\n+\t\tq_vector = vsi->tx_rings[base_queue + i]->q_vector;\n+\n+\t\tif (!q_vector)\n+\t\t\tcontinue;\n+\t}\n+\n+\t/* Reconfigure TX queues using QTX_CTL register */\n+\tret = i40e_channel_config_tx_ring(pf, vsi, ch);\n+\tif (ret) {\n+\t\tdev_info(&pf->pdev->dev,\n+\t\t\t \"failed to configure TX rings for channel %u\\n\",\n+\t\t\t ch->seid);\n+\t\treturn ret;\n+\t}\n+\n+\t/* update 'next_base_queue' */\n+\tatomic_set(&vsi->next_base_queue,\n+\t\t   atomic_read(&vsi->next_base_queue) + ch->num_queue_pairs);\n+\n+\tdev_dbg(&pf->pdev->dev,\n+\t\t\"Added channel: vsi_seid %u, vsi_number %u, stat_counter_idx %u, num_queue_pairs %u, pf->next_base_queue %d\\n\",\n+\t\tch->seid, ch->vsi_number, ch->stat_counter_idx,\n+\t\tch->num_queue_pairs,\n+\t\tatomic_read(&vsi->next_base_queue));\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_setup_channel - setup new channel using uplink element\n+ * @pf: ptr to PF device\n+ * @type: type of channel to be created (VMDq2/VF)\n+ * @uplink_seid: underlying HW switching element (VEB) ID\n+ * @ch: ptr to channel structure\n+ *\n+ * Setup new channel (VSI) based on specified type (VMDq2/VF)\n+ * and uplink switching element (uplink_seid)\n+ **/\n+static bool i40e_setup_channel(struct i40e_pf *pf, struct i40e_vsi *vsi,\n+\t\t\t       struct i40e_channel *ch)\n+{\n+\tu16 seid = vsi->seid;\n+\tu8 vsi_type;\n+\tint ret;\n+\n+\tif (vsi->type == I40E_VSI_MAIN) {\n+\t\tvsi_type = I40E_VSI_VMDQ2;\n+\t} else {\n+\t\tdev_err(&pf->pdev->dev, \"unsupported vsi type(%d) of parent vsi\\n\",\n+\t\t\tvsi->type);\n+\t\treturn false;\n+\t}\n+\n+\t/* underlying switching element */\n+\tseid = pf->vsi[pf->lan_vsi]->uplink_seid;\n+\n+\t/* create channel (VSI), configure TX rings */\n+\tret = i40e_setup_hw_channel(pf, vsi, ch, seid, vsi_type);\n+\tif (ret) {\n+\t\tdev_err(&pf->pdev->dev, \"failed to setup hw_channel\\n\");\n+\t\treturn false;\n+\t}\n+\n+\treturn ch->initialized ? true : false;\n+}\n+\n+/**\n+ * i40e_create_queue_channel - function to create channel\n+ * @vsi: VSI to be configured\n+ * @ch: ptr to channel (it contains channel specific params)\n+ *\n+ * This function creates channel (VSI) using num_queues specified by user,\n+ * reconfigs RSS if needed.\n+ **/\n+int i40e_create_queue_channel(struct i40e_vsi *vsi,\n+\t\t\t      struct i40e_channel *ch)\n+{\n+\tstruct i40e_pf *pf = vsi->back;\n+\tbool reconfig_rss;\n+\tint err;\n+\n+\tif (!ch)\n+\t\treturn -EINVAL;\n+\n+\tif (!ch->num_queue_pairs) {\n+\t\tdev_err(&pf->pdev->dev, \"Invalid num_queues requested: %d\\n\",\n+\t\t\tch->num_queue_pairs);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* validate user requested num_queues for channel */\n+\terr = i40e_validate_num_queues(pf, ch->num_queue_pairs, vsi,\n+\t\t\t\t       &reconfig_rss);\n+\tif (err) {\n+\t\tdev_info(&pf->pdev->dev, \"Failed to validate num_queues (%d)\\n\",\n+\t\t\t ch->num_queue_pairs);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* By default we are in VEPA mode, if this is the first VF/VMDq\n+\t * VSI to be added switch to VEB mode.\n+\t */\n+\tif ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) ||\n+\t    (!i40e_is_any_channel(vsi))) {\n+\t\tif (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) {\n+\t\t\tdev_dbg(&pf->pdev->dev,\n+\t\t\t\t\"Failed to create channel. Override queues (%u) not power of 2\\n\",\n+\t\t\t\tvsi->tc_config.tc_info[0].qcount);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {\n+\t\t\tpf->flags |= I40E_FLAG_VEB_MODE_ENABLED;\n+\n+\t\t\tif (vsi->type == I40E_VSI_MAIN) {\n+\t\t\t\tif (pf->flags & I40E_FLAG_TC_MQPRIO)\n+\t\t\t\t\ti40e_do_reset(pf, I40E_PF_RESET_FLAG,\n+\t\t\t\t\t\t      true);\n+\t\t\t\telse\n+\t\t\t\t\ti40e_do_reset_safe(pf,\n+\t\t\t\t\t\t\t   I40E_PF_RESET_FLAG);\n+\t\t\t}\n+\t\t}\n+\t\t/* now onwards for main VSI, number of queues will be value\n+\t\t * of TC0's queue count\n+\t\t */\n+\t}\n+\n+\t/* By this time, vsi->cnt_q_avail shall be set to non-zero and\n+\t * it should be more than num_queues\n+\t */\n+\tif (!vsi->cnt_q_avail || (vsi->cnt_q_avail < ch->num_queue_pairs)) {\n+\t\tdev_dbg(&pf->pdev->dev,\n+\t\t\t\"Error: cnt_q_avail (%u) less than num_queues %d\\n\",\n+\t\t\tvsi->cnt_q_avail, ch->num_queue_pairs);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* reconfig_rss only if vsi type is MAIN_VSI */\n+\tif (reconfig_rss && (vsi->type == I40E_VSI_MAIN)) {\n+\t\terr = i40e_vsi_reconfig_rss(vsi, ch->num_queue_pairs);\n+\t\tif (err) {\n+\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t \"Error: unable to reconfig rss for num_queues (%u)\\n\",\n+\t\t\t\t ch->num_queue_pairs);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (!i40e_setup_channel(pf, vsi, ch)) {\n+\t\tdev_info(&pf->pdev->dev, \"Failed to setup channel\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdev_info(&pf->pdev->dev,\n+\t\t \"Setup channel (id:%u) utilizing num_queues %d\\n\",\n+\t\t ch->seid, ch->num_queue_pairs);\n+\n+\t/* in case of VF, this will be main SRIOV VSI */\n+\tch->parent_vsi = vsi;\n+\n+\t/* and update main_vsi's count for queue_available to use */\n+\tvsi->cnt_q_avail -= ch->num_queue_pairs;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * i40e_configure_queue_channels - Add queue channel for the given TCs\n+ * @vsi: VSI to be configured\n+ *\n+ * Configures queue channel mapping to the given TCs\n+ **/\n+static int i40e_configure_queue_channels(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch;\n+\tint ret = 0, i;\n+\n+\t/* Create app vsi with the TCs. Main VSI with TC0 is already set up */\n+\tfor (i = 1; i < I40E_MAX_TRAFFIC_CLASS; i++)\n+\t\tif (vsi->tc_config.enabled_tc & BIT(i)) {\n+\t\t\tch = kzalloc(sizeof(*ch), GFP_KERNEL);\n+\t\t\tif (!ch) {\n+\t\t\t\tret = -ENOMEM;\n+\t\t\t\tgoto err_free;\n+\t\t\t}\n+\n+\t\t\tINIT_LIST_HEAD(&ch->list);\n+\t\t\tch->num_queue_pairs =\n+\t\t\t\tvsi->tc_config.tc_info[i].qcount;\n+\t\t\tch->base_queue =\n+\t\t\t\tvsi->tc_config.tc_info[i].qoffset;\n+\n+\t\t\tlist_add_tail(&ch->list, &vsi->ch_list);\n+\n+\t\t\tret = i40e_create_queue_channel(vsi, ch);\n+\t\t\tif (ret) {\n+\t\t\t\tdev_err(&vsi->back->pdev->dev,\n+\t\t\t\t\t\"Failed creating queue channel with TC%d: queues %d\\n\",\n+\t\t\t\t\ti, ch->num_queue_pairs);\n+\t\t\t\tgoto err_free;\n+\t\t\t}\n+\t\t}\n+\treturn ret;\n+\n+err_free:\n+\ti40e_remove_queue_channels(vsi);\n+\treturn ret;\n+}\n+\n+/**\n  * i40e_veb_config_tc - Configure TCs for given VEB\n  * @veb: given VEB\n  * @enabled_tc: TC bitmap\n@@ -5618,10 +6302,18 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)\n \t\tgoto exit;\n \t}\n \n-\t/* Unquiesce VSI */\n-\ti40e_unquiesce_vsi(vsi);\n+\tif (pf->flags & I40E_FLAG_TC_MQPRIO) {\n+\t\tret = i40e_configure_queue_channels(vsi);\n+\t\tif (ret) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t    \"Failed configuring queue channels\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n \n exit:\n+\t/* Unquiesce VSI */\n+\ti40e_unquiesce_vsi(vsi);\n \treturn ret;\n }\n \n@@ -7022,6 +7714,35 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)\n }\n \n /**\n+ * i40e_rebuild_channels - Rebuilds channel VSIs if they existed before reset\n+ * @vsi: PF main vsi\n+ *\n+ * Rebuilds channel VSIs if they existed before reset\n+ **/\n+static int i40e_rebuild_channels(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_channel *ch, *ch_tmp;\n+\ti40e_status ret;\n+\n+\tif (list_empty(&vsi->ch_list))\n+\t\treturn 0;\n+\n+\tlist_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {\n+\t\tif (!ch->initialized)\n+\t\t\tbreak;\n+\t\t/* Proceed with creation of channel (VMDq2) VSI */\n+\t\tret = i40e_add_channel(vsi->back, vsi->uplink_seid, ch);\n+\t\tif (ret) {\n+\t\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t\t \"failed to rebuild channels using uplink_seid %u\\n\",\n+\t\t\t\t vsi->uplink_seid);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n  * i40e_prep_for_reset - prep for the core to reset\n  * @pf: board private structure\n  * @lock_acquired: indicates whether or not the lock has been acquired\n@@ -7286,6 +8007,13 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)\n \t\t}\n \t}\n \n+\t/* PF Main VSI is rebuild by now, go ahead and rebuild channel VSIs\n+\t * for this main VSI if they exist\n+\t */\n+\tret = i40e_rebuild_channels(pf->vsi[pf->lan_vsi]);\n+\tif (ret)\n+\t\tgoto end_unlock;\n+\n \t/* Reconfigure hardware for allowing smaller MSS in the case\n \t * of TSO, so that we avoid the MDD being fired and causing\n \t * a reset in the case of small MSS+TSO.\n@@ -11562,6 +12290,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t\tdev_info(&pdev->dev, \"setup_pf_switch failed: %d\\n\", err);\n \t\tgoto err_vsis;\n \t}\n+\tINIT_LIST_HEAD(&pf->vsi[pf->lan_vsi]->ch_list);\n \n \t/* Make sure flow control is set according to current settings */\n \terr = i40e_set_fc(hw, &set_fc_aq_fail, true);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\nindex 2f848bc..a767f87 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n@@ -423,6 +423,8 @@ struct i40e_ring {\n \t\t\t\t\t * i40e_clean_rx_ring_irq() is called\n \t\t\t\t\t * for this ring.\n \t\t\t\t\t */\n+\n+\tstruct i40e_channel *ch;\n } ____cacheline_internodealigned_in_smp;\n \n static inline bool ring_uses_build_skb(struct i40e_ring *ring)\n",
    "prefixes": [
        "v2",
        "3/6",
        "net-next"
    ]
}