Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/786535/?format=api
{ "id": 786535, "url": "http://patchwork.ozlabs.org/api/patches/786535/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/149976833103.2896.15800483032245869388.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": "<149976833103.2896.15800483032245869388.stgit@anamdev.jf.intel.com>", "list_archive_url": null, "date": "2017-07-11T10:18:51", "name": "[4/6,next-queue] net: i40e: Enable mqprio full offload mode in the i40e driver for configuring TCs and queue mapping", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "e5986b84856057d211aab74ba914e0311a26bf48", "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/149976833103.2896.15800483032245869388.stgit@anamdev.jf.intel.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/786535/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/786535/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" ], "Received": [ "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\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 3x6J3L5yxfz9s0Z\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 11 Jul 2017 20:19:26 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 2C7B986E45;\n\tTue, 11 Jul 2017 10:19:25 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id mmWPn3ZULUok; Tue, 11 Jul 2017 10:19:22 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 1663886FBE;\n\tTue, 11 Jul 2017 10:19:22 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 8CEE81C2082\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 11 Jul 2017 10:19:20 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 8366D30183\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 11 Jul 2017 10:19:20 +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 EsjSliWXlR8C for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 11 Jul 2017 10:19:19 +0000 (UTC)", "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby silver.osuosl.org (Postfix) with ESMTPS id 0DF4A2FE89\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 11 Jul 2017 10:19:19 +0000 (UTC)", "from orsmga004.jf.intel.com ([10.7.209.38])\n\tby fmsmga105.fm.intel.com with ESMTP; 11 Jul 2017 03:19:18 -0700", "from anamdev.jf.intel.com ([10.166.29.110])\n\tby orsmga004.jf.intel.com with ESMTP; 11 Jul 2017 03:19:18 -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.40,345,1496127600\"; d=\"scan'208\";a=\"106920117\"", "From": "Amritha Nambiar <amritha.nambiar@intel.com>", "To": "intel-wired-lan@lists.osuosl.org, jeffrey.t.kirsher@intel.com", "Date": "Tue, 11 Jul 2017 03:18:51 -0700", "Message-ID": "<149976833103.2896.15800483032245869388.stgit@anamdev.jf.intel.com>", "In-Reply-To": "<149976762072.2896.5722904915197643856.stgit@anamdev.jf.intel.com>", "References": "<149976762072.2896.5722904915197643856.stgit@anamdev.jf.intel.com>", "User-Agent": "StGit/0.17.1-dirty", "MIME-Version": "1.0", "Cc": "netdev@vger.kernel.org, mitch.a.williams@intel.com", "Subject": "[Intel-wired-lan] [PATCH 4/6] [next-queue]net: i40e: Enable mqprio\n\tfull offload mode in the i40e driver for configuring TCs and queue\n\tmapping", "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": "The i40e driver is modified to enable the new mqprio hardware\noffload mode and factor the TCs and queue configuration by\ncreating channel VSIs. In this mode, the priority to traffic\nclass mapping and the user specified queue ranges are used\nto configure the traffic classes when the 'hw' option is set\nto 2.\n\nExample:\n# tc qdisc add dev eth0 root mqprio num_tc 4\\\n map 0 0 0 0 1 2 2 3 queues 2@0 2@2 1@4 1@5 hw 2\n\n# tc qdisc show dev eth0\n\nqdisc mqprio 8038: root tc 4 map 0 0 0 0 1 2 2 3 0 0 0 0 0 0 0 0\n queues:(0:1) (2:3) (4:4) (5:5)\n\nThe HW channels created are removed and all the queue configuration\nis set to default when the qdisc is detached from the root of the\ndevice.\n\n# tc qdisc del dev eth0 root\n\nThis patch also disables setting up channels via ethtool (ethtool -L)\nwhen the TCs are configured using mqprio scheduler.\n\nThe patch also limits setting ethtool Rx flow hash indirection\n(ethtool -X eth0 equal N) to max queues configured via mqprio.\nThe Rx flow hash indirection input through ethtool should be\nvalidated so that it is within in the queue range configured via\ntc/mqprio. The bound checking is achieved by reporting the current\nrss size to the kernel when queues are configured via mqprio.\n\nExample:\n# tc qdisc add dev eth0 root mqprio num_tc 4\\\n map 0 0 0 1 0 2 3 0 queues 2@0 4@2 8@6 11@14 hw 2\n\n# ethtool -X eth0 equal 12\nCannot set RX flow hash configuration: Invalid argument\n\nSigned-off-by: Amritha Nambiar <amritha.nambiar@intel.com>\n---\n drivers/net/ethernet/intel/i40e/i40e.h | 3 \n drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 \n drivers/net/ethernet/intel/i40e/i40e_main.c | 442 ++++++++++++++++++------\n 3 files changed, 342 insertions(+), 111 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 93bb527..501d62e 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -54,6 +54,7 @@\n #include <linux/clocksource.h>\n #include <linux/net_tstamp.h>\n #include <linux/ptp_clock_kernel.h>\n+#include <net/pkt_cls.h>\n #include \"i40e_type.h\"\n #include \"i40e_prototype.h\"\n #include \"i40e_client.h\"\n@@ -697,6 +698,7 @@ struct i40e_vsi {\n \tenum i40e_vsi_type type; /* VSI type, e.g., LAN, FCoE, etc */\n \ts16 vf_id;\t\t/* Virtual function ID for SRIOV VSIs */\n \n+\tstruct tc_mqprio_qopt_offload mqprio_qopt; /* queue parameters */\n \tstruct i40e_tc_configuration tc_config;\n \tstruct i40e_aqc_vsi_properties_data info;\n \n@@ -722,6 +724,7 @@ struct i40e_vsi {\n \tu16 cnt_q_avail; /* num of queues available for channel usage */\n \tu16 orig_rss_size;\n \tu16 current_rss_size;\n+\tbool reconfig_rss;\n \n \t/* keeps track of next_base_queue to be used for channel setup */\n \tatomic_t next_base_queue;\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\nindex a868c8d..d61af22 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n@@ -2626,7 +2626,7 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,\n \n \tswitch (cmd->cmd) {\n \tcase ETHTOOL_GRXRINGS:\n-\t\tcmd->data = vsi->num_queue_pairs;\n+\t\tcmd->data = vsi->rss_size;\n \t\tret = 0;\n \t\tbreak;\n \tcase ETHTOOL_GRXFH:\n@@ -3871,6 +3871,12 @@ static int i40e_set_channels(struct net_device *dev,\n \tif (vsi->type != I40E_VSI_MAIN)\n \t\treturn -EINVAL;\n \n+\t/* We do not support setting channels via ethtool when TCs are\n+\t * configured through mqprio\n+\t */\n+\tif (pf->flags & I40E_FLAG_TC_MQPRIO)\n+\t\treturn -EINVAL;\n+\n \t/* verify they are not requesting separate vectors */\n \tif (!count || ch->rx_count || ch->tx_count)\n \t\treturn -EINVAL;\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 54a6275..40084b7 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -1578,6 +1578,169 @@ static int i40e_set_mac(struct net_device *netdev, void *p)\n }\n \n /**\n+ * i40e_config_rss_aq - Prepare for RSS using AQ commands\n+ * @vsi: vsi structure\n+ * @seed: RSS hash seed\n+ **/\n+static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed,\n+\t\t\t u8 *lut, u16 lut_size)\n+{\n+\tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_hw *hw = &pf->hw;\n+\tint ret = 0;\n+\n+\tif (seed) {\n+\t\tstruct i40e_aqc_get_set_rss_key_data *seed_dw =\n+\t\t\t(struct i40e_aqc_get_set_rss_key_data *)seed;\n+\t\tret = i40e_aq_set_rss_key(hw, vsi->id, seed_dw);\n+\t\tif (ret) {\n+\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t \"Cannot set RSS key, err %s aq_err %s\\n\",\n+\t\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\tif (lut) {\n+\t\tbool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false;\n+\n+\t\tret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, lut, lut_size);\n+\t\tif (ret) {\n+\t\t\tdev_info(&pf->pdev->dev,\n+\t\t\t\t \"Cannot set RSS lut, err %s aq_err %s\\n\",\n+\t\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_vsi_config_rss - Prepare for VSI(VMDq) RSS if used\n+ * @vsi: VSI structure\n+ **/\n+static int i40e_vsi_config_rss(struct i40e_vsi *vsi)\n+{\n+\tu8 seed[I40E_HKEY_ARRAY_SIZE];\n+\tstruct i40e_pf *pf = vsi->back;\n+\tu8 *lut;\n+\tint ret;\n+\n+\tif (!(pf->hw_features & I40E_HW_RSS_AQ_CAPABLE))\n+\t\treturn 0;\n+\tif (!vsi->rss_size)\n+\t\tvsi->rss_size = min_t(int, pf->alloc_rss_size,\n+\t\t\t\t vsi->num_queue_pairs);\n+\tif (!vsi->rss_size)\n+\t\treturn -EINVAL;\n+\tlut = kzalloc(vsi->rss_table_size, GFP_KERNEL);\n+\tif (!lut)\n+\t\treturn -ENOMEM;\n+\n+\t/* Use the user configured hash keys and lookup table if there is one,\n+\t * otherwise use default\n+\t */\n+\tif (vsi->rss_lut_user)\n+\t\tmemcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);\n+\telse\n+\t\ti40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size);\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+\tret = i40e_config_rss_aq(vsi, seed, lut, vsi->rss_table_size);\n+\tkfree(lut);\n+\treturn ret;\n+}\n+\n+/**\n+ * i40e_vsi_setup_queue_map_mqprio - Prepares VSI tc_config to have queue\n+ * configurations based on MQPRIO options.\n+ * @vsi: the VSI being configured,\n+ * @ctxt: VSI context structure\n+ * @enabled_tc: number of traffic classes to enable\n+ **/\n+static int i40e_vsi_setup_queue_map_mqprio(struct i40e_vsi *vsi,\n+\t\t\t\t\t struct i40e_vsi_context *ctxt,\n+\t\t\t\t\t u8 enabled_tc)\n+{\n+\tu16 qcount = 0, max_qcount, qmap, sections = 0;\n+\tint i, override_q, pow, num_qps, ret;\n+\tu8 netdev_tc = 0, offset = 0;\n+\n+\tif (vsi->type != I40E_VSI_MAIN)\n+\t\treturn -EINVAL;\n+\tsections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;\n+\tsections |= I40E_AQ_VSI_PROP_SCHED_VALID;\n+\tvsi->tc_config.numtc = vsi->mqprio_qopt.qopt.num_tc;\n+\tvsi->tc_config.enabled_tc = enabled_tc ? enabled_tc : 1;\n+\tnum_qps = vsi->mqprio_qopt.qopt.count[0];\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+\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 offset/count for all TCs for given VSI */\n+\tmax_qcount = vsi->mqprio_qopt.qopt.count[0];\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\t/* See if the given TC is enabled for the given VSI */\n+\t\tif (vsi->tc_config.enabled_tc & BIT(i)) {\n+\t\t\toffset = vsi->mqprio_qopt.qopt.offset[i];\n+\t\t\tqcount = vsi->mqprio_qopt.qopt.count[i];\n+\t\t\tif (qcount > max_qcount)\n+\t\t\t\tmax_qcount = qcount;\n+\t\t\tvsi->tc_config.tc_info[i].qoffset = offset;\n+\t\t\tvsi->tc_config.tc_info[i].qcount = qcount;\n+\t\t\tvsi->tc_config.tc_info[i].netdev_tc = netdev_tc++;\n+\t\t} else {\n+\t\t\t/* TC is not enabled so set the offset to\n+\t\t\t * default queue and allocate one queue\n+\t\t\t * for the given TC.\n+\t\t\t */\n+\t\t\tvsi->tc_config.tc_info[i].qoffset = 0;\n+\t\t\tvsi->tc_config.tc_info[i].qcount = 1;\n+\t\t\tvsi->tc_config.tc_info[i].netdev_tc = 0;\n+\t\t}\n+\t}\n+\n+\t/* Set actual Tx/Rx queue pairs */\n+\tvsi->num_queue_pairs = offset + qcount;\n+\n+\t/* Setup queue TC[0].qmap for given VSI context */\n+\tctxt->info.tc_mapping[0] = cpu_to_le16(qmap);\n+\tctxt->info.mapping_flags |= cpu_to_le16(I40E_AQ_VSI_QUE_MAP_CONTIG);\n+\tctxt->info.queue_mapping[0] = cpu_to_le16(vsi->base_queue);\n+\tctxt->info.valid_sections |= cpu_to_le16(sections);\n+\n+\t/* Reconfigure RSS for main VSI with max queue count */\n+\tvsi->rss_size = max_qcount;\n+\tret = i40e_vsi_config_rss(vsi);\n+\tif (ret) {\n+\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t \"Failed to reconfig rss for num_queues (%u)\\n\",\n+\t\t\t max_qcount);\n+\t\treturn ret;\n+\t}\n+\tvsi->reconfig_rss = true;\n+\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\"Reconfigured rss with num_queues (%u)\\n\", max_qcount);\n+\n+\t/* Find queue count available for channel VSIs and starting offset\n+\t * for channel VSIs\n+\t */\n+\toverride_q = vsi->mqprio_qopt.qopt.count[0];\n+\tif (override_q && (override_q < vsi->num_queue_pairs)) {\n+\t\tvsi->cnt_q_avail = vsi->num_queue_pairs - override_q;\n+\t\tatomic_set(&vsi->next_base_queue, override_q);\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n * i40e_vsi_setup_queue_map - Setup a VSI queue map based on enabled_tc\n * @vsi: the VSI being setup\n * @ctxt: VSI context structure\n@@ -1615,7 +1778,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,\n \t\t\tnumtc = 1;\n \t\t}\n \t} else {\n-\t\t/* At least TC0 is enabled in case of non-DCB case */\n+\t\t/* At least TC0 is enabled in non-DCB, non-MQPRIO case */\n \t\tnumtc = 1;\n \t}\n \n@@ -3164,6 +3327,7 @@ static void i40e_vsi_config_dcb_rings(struct i40e_vsi *vsi)\n \t\t\trx_ring->dcb_tc = 0;\n \t\t\ttx_ring->dcb_tc = 0;\n \t\t}\n+\t\treturn;\n \t}\n \n \tfor (n = 0; n < I40E_MAX_TRAFFIC_CLASS; n++) {\n@@ -4872,6 +5036,24 @@ static u8 i40e_dcb_get_enabled_tc(struct i40e_dcbx_config *dcbcfg)\n }\n \n /**\n+ * i40e_mqprio_get_enabled_tc - Get enabled traffic classes\n+ * @pf: PF being queried\n+ *\n+ * Query the current MQPRIO configuration and return the number of\n+ * traffic classes enabled.\n+ **/\n+static u8 i40e_mqprio_get_enabled_tc(struct i40e_pf *pf)\n+{\n+\tstruct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];\n+\tu8 num_tc = vsi->mqprio_qopt.qopt.num_tc;\n+\tu8 enabled_tc = 1, i;\n+\n+\tfor (i = 1; i < num_tc; i++)\n+\t\tenabled_tc |= BIT(i);\n+\treturn enabled_tc;\n+}\n+\n+/**\n * i40e_pf_get_num_tc - Get enabled traffic classes for PF\n * @pf: PF being queried\n *\n@@ -4884,7 +5066,10 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)\n \tu8 num_tc = 0;\n \tstruct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;\n \n-\t/* If DCB is not enabled then always in single TC */\n+\tif (pf->flags & I40E_FLAG_TC_MQPRIO)\n+\t\treturn pf->vsi[pf->lan_vsi]->mqprio_qopt.qopt.num_tc;\n+\n+\t/* If neither MQPRIO nor DCB is enabled, then always use single TC */\n \tif (!(pf->flags & I40E_FLAG_DCB_ENABLED))\n \t\treturn 1;\n \n@@ -4913,7 +5098,12 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)\n **/\n static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)\n {\n-\t/* If DCB is not enabled for this PF then just return default TC */\n+\tif (pf->flags & I40E_FLAG_TC_MQPRIO)\n+\t\treturn i40e_mqprio_get_enabled_tc(pf);\n+\n+\t/* If neither MQPRIO nor DCB is enabled for this PF then just return\n+\t * default TC\n+\t */\n \tif (!(pf->flags & I40E_FLAG_DCB_ENABLED))\n \t\treturn I40E_DEFAULT_TRAFFIC_CLASS;\n \n@@ -5003,6 +5193,9 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,\n \ti40e_status ret;\n \tint i;\n \n+\tif ((vsi->back->flags & I40E_FLAG_TC_MQPRIO) ||\n+\t !vsi->mqprio_qopt.qopt.hw)\n+\t\treturn 0;\n \tbw_data.tc_valid_bits = enabled_tc;\n \tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)\n \t\tbw_data.tc_bw_credits[i] = bw_share[i];\n@@ -5065,6 +5258,9 @@ static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n \t\t\t\t\tvsi->tc_config.tc_info[i].qoffset);\n \t}\n \n+\tif (pf->flags & I40E_FLAG_TC_MQPRIO)\n+\t\treturn;\n+\n \t/* Assign UP2TC map for the VSI */\n \tfor (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {\n \t\t/* Get the actual TC# for the UP */\n@@ -5115,7 +5311,8 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n \tint i;\n \n \t/* Check if enabled_tc is same as existing or new TCs */\n-\tif (vsi->tc_config.enabled_tc == enabled_tc)\n+\tif (vsi->tc_config.enabled_tc == enabled_tc &&\n+\t vsi->mqprio_qopt.qopt.hw != TC_MQPRIO_HW_OFFLOAD)\n \t\treturn ret;\n \n \t/* Enable ETS TCs with equal BW Share for now across all VSIs */\n@@ -5138,15 +5335,37 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)\n \tctxt.vf_num = 0;\n \tctxt.uplink_seid = vsi->uplink_seid;\n \tctxt.info = vsi->info;\n-\ti40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);\n+\tif (vsi->back->flags & I40E_FLAG_TC_MQPRIO) {\n+\t\tret = i40e_vsi_setup_queue_map_mqprio(vsi, &ctxt, enabled_tc);\n+\t\tif (ret)\n+\t\t\tgoto out;\n+\t} else {\n+\t\ti40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);\n+\t}\n \n+\t/* On destroying the qdisc, reset vsi->rss_size, as number of enabled\n+\t * queues changed.\n+\t */\n+\tif (!vsi->mqprio_qopt.qopt.hw && vsi->reconfig_rss) {\n+\t\tvsi->rss_size = min_t(int, vsi->back->alloc_rss_size,\n+\t\t\t\t vsi->num_queue_pairs);\n+\t\tret = i40e_vsi_config_rss(vsi);\n+\t\tif (ret) {\n+\t\t\tdev_info(&vsi->back->pdev->dev,\n+\t\t\t\t \"Failed to reconfig rss for num_queues\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t\tvsi->reconfig_rss = false;\n+\t}\n \tif (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {\n \t\tctxt.info.valid_sections |=\n \t\t\t\tcpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);\n \t\tctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;\n \t}\n \n-\t/* Update the VSI after updating the VSI queue-mapping information */\n+\t/* Update the VSI after updating the VSI queue-mapping\n+\t * information\n+\t */\n \tret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);\n \tif (ret) {\n \t\tdev_info(&vsi->back->pdev->dev,\n@@ -6238,48 +6457,131 @@ void i40e_down(struct i40e_vsi *vsi)\n }\n \n /**\n+ * i40e_validate_mqprio_qopt- validate queue mapping info\n+ * @vsi: the VSI being configured\n+ * @mqprio_qopt: queue parametrs\n+ **/\n+static int i40e_validate_mqprio_qopt(struct i40e_vsi *vsi,\n+\t\t\t\t struct tc_mqprio_qopt_offload *mqprio_qopt)\n+{\n+\tint i;\n+\n+\tif ((mqprio_qopt->qopt.offset[0] != 0) ||\n+\t (mqprio_qopt->qopt.num_tc < 1) ||\n+\t (mqprio_qopt->qopt.num_tc > I40E_MAX_TRAFFIC_CLASS))\n+\t\treturn -EINVAL;\n+\tfor (i = 0; ; i++) {\n+\t\tif (!mqprio_qopt->qopt.count[i])\n+\t\t\treturn -EINVAL;\n+\t\tif (mqprio_qopt->min_rate[i] || mqprio_qopt->max_rate[i])\n+\t\t\treturn -EINVAL;\n+\t\tif (i >= mqprio_qopt->qopt.num_tc - 1)\n+\t\t\tbreak;\n+\t\tif (mqprio_qopt->qopt.offset[i + 1] !=\n+\t\t (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i]))\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (vsi->num_queue_pairs <\n+\t (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i])) {\n+\t\treturn -EINVAL;\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n * i40e_setup_tc - configure multiple traffic classes\n * @netdev: net device to configure\n- * @tc: number of traffic classes to enable\n+ * @tc: pointer to struct tc_to_netdev\n **/\n-static int i40e_setup_tc(struct net_device *netdev, u8 tc)\n+static int i40e_setup_tc(struct net_device *netdev, struct tc_to_netdev *tc)\n {\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n \tstruct i40e_vsi *vsi = np->vsi;\n \tstruct i40e_pf *pf = vsi->back;\n-\tu8 enabled_tc = 0;\n+\tu8 enabled_tc = 0, num_tc = 0, hw = 0;\n \tint ret = -EINVAL;\n \tint i;\n \n-\t/* Check if DCB enabled to continue */\n-\tif (!(pf->flags & I40E_FLAG_DCB_ENABLED)) {\n-\t\tnetdev_info(netdev, \"DCB is not enabled for adapter\\n\");\n-\t\tgoto exit;\n-\t}\n+\tif (tc->type == TC_SETUP_MQPRIO) {\n+\t\thw = tc->mqprio->hw;\n+\t\tnum_tc = tc->mqprio->num_tc;\n+\t} else if (tc->type == TC_SETUP_MQPRIO_EXT) {\n+\t\thw = tc->mqprio_qopt->qopt.hw;\n+\t\tnum_tc = tc->mqprio_qopt->qopt.num_tc;\n+\t}\n+\tif (!hw) {\n+\t\tpf->flags &= ~I40E_FLAG_TC_MQPRIO;\n+\t\tif (tc->type == TC_SETUP_MQPRIO_EXT)\n+\t\t\tmemcpy(&vsi->mqprio_qopt, tc->mqprio_qopt,\n+\t\t\t sizeof(*tc->mqprio_qopt));\n+\t\tgoto config_tc;\n+\t}\n+\tswitch (hw) {\n+\tcase TC_MQPRIO_HW_OFFLOAD_TCS:\n+\t\tpf->flags &= ~I40E_FLAG_TC_MQPRIO;\n+\n+\t\t/* Check if DCB enabled to continue */\n+\t\tif (!(pf->flags & I40E_FLAG_DCB_ENABLED)) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"DCB is not enabled for adapter\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n \n-\t/* Check if MFP enabled */\n-\tif (pf->flags & I40E_FLAG_MFP_ENABLED) {\n-\t\tnetdev_info(netdev, \"Configuring TC not supported in MFP mode\\n\");\n-\t\tgoto exit;\n-\t}\n+\t\t/* Check if MFP enabled */\n+\t\tif (pf->flags & I40E_FLAG_MFP_ENABLED) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"Configuring TC not supported in MFP mode\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n \n-\t/* Check whether tc count is within enabled limit */\n-\tif (tc > i40e_pf_get_num_tc(pf)) {\n-\t\tnetdev_info(netdev, \"TC count greater than enabled on link for adapter\\n\");\n-\t\tgoto exit;\n+\t\t/* Check whether tc count is within enabled limit */\n+\t\tif (num_tc > i40e_pf_get_num_tc(pf)) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"TC count greater than enabled on link for adapter\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n+\t\tbreak;\n+\tcase TC_MQPRIO_HW_OFFLOAD:\n+\t\tif (pf->flags & I40E_FLAG_DCB_ENABLED) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"Full offload of TC Mqprio options is not supported when DCB is enabled\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n+\n+\t\t/* Check if MFP enabled */\n+\t\tif (pf->flags & I40E_FLAG_MFP_ENABLED) {\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"Configuring TC not supported in MFP mode\\n\");\n+\t\t\tgoto exit;\n+\t\t}\n+\t\tret = i40e_validate_mqprio_qopt(vsi, tc->mqprio_qopt);\n+\t\tif (ret)\n+\t\t\tgoto exit;\n+\t\tmemcpy(&vsi->mqprio_qopt, tc->mqprio_qopt,\n+\t\t sizeof(*tc->mqprio_qopt));\n+\t\tpf->flags |= I40E_FLAG_TC_MQPRIO;\n+\t\tpf->flags &= ~I40E_FLAG_DCB_ENABLED;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n \t}\n \n+config_tc:\n \t/* Generate TC map for number of tc requested */\n-\tfor (i = 0; i < tc; i++)\n+\tfor (i = 0; i < num_tc; i++)\n \t\tenabled_tc |= BIT(i);\n \n \t/* Requesting same TC configuration as already enabled */\n-\tif (enabled_tc == vsi->tc_config.enabled_tc)\n+\tif (enabled_tc == vsi->tc_config.enabled_tc &&\n+\t hw != TC_MQPRIO_HW_OFFLOAD)\n \t\treturn 0;\n \n \t/* Quiesce VSI queues */\n \ti40e_quiesce_vsi(vsi);\n \n+\tif (!hw && !(pf->flags & I40E_FLAG_TC_MQPRIO))\n+\t\ti40e_remove_queue_channels(vsi);\n+\n \t/* Configure VSI for enabled TCs */\n \tret = i40e_vsi_config_tc(vsi, enabled_tc);\n \tif (ret) {\n@@ -6297,7 +6599,11 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)\n \t\t}\n \t}\n \n+\tgoto out;\n exit:\n+\t/* Reset the configuration data */\n+\tmemset(&vsi->tc_config, 0, sizeof(vsi->tc_config));\n+out:\n \t/* Unquiesce VSI */\n \ti40e_unquiesce_vsi(vsi);\n \treturn ret;\n@@ -6307,12 +6613,7 @@ static int __i40e_setup_tc(struct net_device *netdev, u32 handle,\n \t\t\t u32 chain_index, __be16 proto,\n \t\t\t struct tc_to_netdev *tc)\n {\n-\tif (tc->type != TC_SETUP_MQPRIO)\n-\t\treturn -EINVAL;\n-\n-\ttc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;\n-\n-\treturn i40e_setup_tc(netdev, tc->mqprio->num_tc);\n+\treturn i40e_setup_tc(netdev, tc);\n }\n \n /**\n@@ -9110,45 +9411,6 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)\n }\n \n /**\n- * i40e_config_rss_aq - Prepare for RSS using AQ commands\n- * @vsi: vsi structure\n- * @seed: RSS hash seed\n- **/\n-static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed,\n-\t\t\t u8 *lut, u16 lut_size)\n-{\n-\tstruct i40e_pf *pf = vsi->back;\n-\tstruct i40e_hw *hw = &pf->hw;\n-\tint ret = 0;\n-\n-\tif (seed) {\n-\t\tstruct i40e_aqc_get_set_rss_key_data *seed_dw =\n-\t\t\t(struct i40e_aqc_get_set_rss_key_data *)seed;\n-\t\tret = i40e_aq_set_rss_key(hw, vsi->id, seed_dw);\n-\t\tif (ret) {\n-\t\t\tdev_info(&pf->pdev->dev,\n-\t\t\t\t \"Cannot set RSS key, err %s aq_err %s\\n\",\n-\t\t\t\t i40e_stat_str(hw, ret),\n-\t\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n-\t\t\treturn ret;\n-\t\t}\n-\t}\n-\tif (lut) {\n-\t\tbool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false;\n-\n-\t\tret = i40e_aq_set_rss_lut(hw, vsi->id, pf_lut, lut, lut_size);\n-\t\tif (ret) {\n-\t\t\tdev_info(&pf->pdev->dev,\n-\t\t\t\t \"Cannot set RSS lut, err %s aq_err %s\\n\",\n-\t\t\t\t i40e_stat_str(hw, ret),\n-\t\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n-\t\t\treturn ret;\n-\t\t}\n-\t}\n-\treturn ret;\n-}\n-\n-/**\n * i40e_get_rss_aq - Get RSS keys and lut by using AQ commands\n * @vsi: Pointer to vsi structure\n * @seed: Buffter to store the hash keys\n@@ -9195,46 +9457,6 @@ static int i40e_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed,\n }\n \n /**\n- * i40e_vsi_config_rss - Prepare for VSI(VMDq) RSS if used\n- * @vsi: VSI structure\n- **/\n-static int i40e_vsi_config_rss(struct i40e_vsi *vsi)\n-{\n-\tu8 seed[I40E_HKEY_ARRAY_SIZE];\n-\tstruct i40e_pf *pf = vsi->back;\n-\tu8 *lut;\n-\tint ret;\n-\n-\tif (!(pf->hw_features & I40E_HW_RSS_AQ_CAPABLE))\n-\t\treturn 0;\n-\n-\tif (!vsi->rss_size)\n-\t\tvsi->rss_size = min_t(int, pf->alloc_rss_size,\n-\t\t\t\t vsi->num_queue_pairs);\n-\tif (!vsi->rss_size)\n-\t\treturn -EINVAL;\n-\n-\tlut = kzalloc(vsi->rss_table_size, GFP_KERNEL);\n-\tif (!lut)\n-\t\treturn -ENOMEM;\n-\t/* Use the user configured hash keys and lookup table if there is one,\n-\t * otherwise use default\n-\t */\n-\tif (vsi->rss_lut_user)\n-\t\tmemcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);\n-\telse\n-\t\ti40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size);\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-\tret = i40e_config_rss_aq(vsi, seed, lut, vsi->rss_table_size);\n-\tkfree(lut);\n-\n-\treturn ret;\n-}\n-\n-/**\n * i40e_config_rss_reg - Configure RSS keys and lut by writing registers\n * @vsi: Pointer to vsi structure\n * @seed: RSS hash seed\n", "prefixes": [ "4/6", "next-queue" ] }