get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 8496,
    "url": "https://patches.dpdk.org/api/patches/8496/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1446307051-29283-4-git-send-email-jingjing.wu@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1446307051-29283-4-git-send-email-jingjing.wu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1446307051-29283-4-git-send-email-jingjing.wu@intel.com",
    "date": "2015-10-31T15:57:25",
    "name": "[dpdk-dev,v3,3/9] i40e: enable DCB feature on FVL",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "2cf262fa7348160eba9d7f0f83c944fa8122443a",
    "submitter": {
        "id": 47,
        "url": "https://patches.dpdk.org/api/people/47/?format=api",
        "name": "Jingjing Wu",
        "email": "jingjing.wu@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1446307051-29283-4-git-send-email-jingjing.wu@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/8496/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/8496/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 3F8598E73;\n\tSat, 31 Oct 2015 16:57:50 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 181938D9A\n\tfor <dev@dpdk.org>; Sat, 31 Oct 2015 16:57:46 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga103.fm.intel.com with ESMTP; 31 Oct 2015 08:57:46 -0700",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby fmsmga001.fm.intel.com with ESMTP; 31 Oct 2015 08:57:45 -0700",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id t9VFvgAr032719;\n\tSat, 31 Oct 2015 23:57:42 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t9VFvdgi029680; Sat, 31 Oct 2015 23:57:41 +0800",
            "(from wujingji@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t9VFvdt5029676; \n\tSat, 31 Oct 2015 23:57:39 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.20,224,1444719600\"; d=\"scan'208\";a=\"823856848\"",
        "From": "Jingjing Wu <jingjing.wu@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Sat, 31 Oct 2015 23:57:25 +0800",
        "Message-Id": "<1446307051-29283-4-git-send-email-jingjing.wu@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1446307051-29283-1-git-send-email-jingjing.wu@intel.com>",
        "References": "<1446108827-7907-1-git-send-email-jingjing.wu@intel.com>\n\t<1446307051-29283-1-git-send-email-jingjing.wu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 3/9] i40e: enable DCB feature on FVL",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch enables DCB feature on Intel XL710/X710 NICs. It includes:\n  Receive queue classification based on traffic class\n  Round Robin ETS schedule (rx and tx)\n  Priority flow control\n\nSigned-off-by: Jingjing Wu <jingjing.wu@intel.com>\n---\n doc/guides/rel_notes/release_2_2.rst |   2 +\n drivers/net/i40e/i40e_ethdev.c       | 532 ++++++++++++++++++++++++++++++++++-\n drivers/net/i40e/i40e_ethdev.h       |  14 +\n drivers/net/i40e/i40e_rxtx.c         |  32 ++-\n drivers/net/i40e/i40e_rxtx.h         |   2 +\n 5 files changed, 568 insertions(+), 14 deletions(-)",
    "diff": "diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst\nindex 1857e1d..ddfd322 100644\n--- a/doc/guides/rel_notes/release_2_2.rst\n+++ b/doc/guides/rel_notes/release_2_2.rst\n@@ -45,6 +45,8 @@ New Features\n \n * **Added port hotplug support to xenvirt.**\n \n+* **Added support DCB on PF to the i40e driver.**\n+\n \n Resolved Issues\n ---------------\ndiff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex 016838a..ce4efb2 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -56,6 +56,7 @@\n #include \"base/i40e_adminq_cmd.h\"\n #include \"base/i40e_type.h\"\n #include \"base/i40e_register.h\"\n+#include \"base/i40e_dcb.h\"\n #include \"i40e_ethdev.h\"\n #include \"i40e_rxtx.h\"\n #include \"i40e_pf.h\"\n@@ -134,6 +135,10 @@\n #define I40E_PRTTSYN_TSYNENA  0x80000000\n #define I40E_PRTTSYN_TSYNTYPE 0x0e000000\n \n+#define I40E_MAX_PERCENT            100\n+#define I40E_DEFAULT_DCB_APP_NUM    1\n+#define I40E_DEFAULT_DCB_APP_PRIO   3\n+\n static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev);\n static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev);\n static int i40e_dev_configure(struct rte_eth_dev *dev);\n@@ -189,6 +194,8 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);\n static int i40e_pf_setup(struct i40e_pf *pf);\n static int i40e_dev_rxtx_init(struct i40e_pf *pf);\n static int i40e_vmdq_setup(struct rte_eth_dev *dev);\n+static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);\n+static int i40e_dcb_setup(struct rte_eth_dev *dev);\n static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,\n \t\tbool offset_loaded, uint64_t *offset, uint64_t *stat);\n static void i40e_stat_update_48(struct i40e_hw *hw,\n@@ -517,11 +524,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)\n \t\t     ((hw->nvm.version >> 4) & 0xff),\n \t\t     (hw->nvm.version & 0xf), hw->nvm.eetrack);\n \n-\t/* Disable LLDP */\n-\tret = i40e_aq_stop_lldp(hw, true, NULL);\n-\tif (ret != I40E_SUCCESS) /* Its failure can be ignored */\n-\t\tPMD_INIT_LOG(INFO, \"Failed to stop lldp\");\n-\n \t/* Clear PXE mode */\n \ti40e_clear_pxe_mode(hw);\n \n@@ -642,6 +644,13 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)\n \t/* initialize mirror rule list */\n \tTAILQ_INIT(&pf->mirror_list);\n \n+\t/* Init dcb to sw mode by default */\n+\tret = i40e_dcb_init_configure(dev, TRUE);\n+\tif (ret != I40E_SUCCESS) {\n+\t\tPMD_INIT_LOG(INFO, \"Failed to init dcb.\");\n+\t\tpf->flags &= ~I40E_FLAG_DCB;\n+\t}\n+\n \treturn 0;\n \n err_mac_alloc:\n@@ -728,7 +737,7 @@ i40e_dev_configure(struct rte_eth_dev *dev)\n \t\tI40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n \tenum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode;\n-\tint ret;\n+\tint i, ret;\n \n \t/* Initialize to TRUE. If any of Rx queues doesn't meet the\n \t * bulk allocation or vector Rx preconditions we will reset it.\n@@ -773,8 +782,27 @@ i40e_dev_configure(struct rte_eth_dev *dev)\n \t\tif (ret)\n \t\t\tgoto err;\n \t}\n+\n+\tif (mq_mode & ETH_MQ_RX_DCB_FLAG) {\n+\t\tret = i40e_dcb_setup(dev);\n+\t\tif (ret) {\n+\t\t\tPMD_DRV_LOG(ERR, \"failed to configure DCB.\");\n+\t\t\tgoto err_dcb;\n+\t\t}\n+\t}\n+\n \treturn 0;\n+\n+err_dcb:\n+\t/* need to release vmdq resource if exists */\n+\tfor (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {\n+\t\ti40e_vsi_release(pf->vmdq[i].vsi);\n+\t\tpf->vmdq[i].vsi = NULL;\n+\t}\n+\trte_free(pf->vmdq);\n+\tpf->vmdq = NULL;\n err:\n+\t/* need to release fdir resource if exists */\n \ti40e_fdir_teardown(pf);\n \treturn ret;\n }\n@@ -2517,6 +2545,9 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)\n \t\t */\n \t}\n \n+\tif (hw->func_caps.dcb)\n+\t\tpf->flags |= I40E_FLAG_DCB;\n+\n \tif (sum_vsis > pf->max_num_vsi ||\n \t\tsum_queues > hw->func_caps.num_rx_qp) {\n \t\tPMD_INIT_LOG(ERR, \"VSI/QUEUE setting can't be satisfied\");\n@@ -2922,7 +2953,7 @@ i40e_vsi_config_tc_queue_mapping(struct i40e_vsi *vsi,\n \t\t\t\t struct i40e_aqc_vsi_properties_data *info,\n \t\t\t\t uint8_t enabled_tcmap)\n {\n-\tint ret, total_tc = 0, i;\n+\tint ret, i, total_tc = 0;\n \tuint16_t qpnum_per_tc, bsf, qp_idx;\n \n \tret = validate_tcmap_parameter(vsi, enabled_tcmap);\n@@ -5479,11 +5510,6 @@ i40e_pf_config_mq_rx(struct i40e_pf *pf)\n \tint ret = 0;\n \tenum rte_eth_rx_mq_mode mq_mode = pf->dev_data->dev_conf.rxmode.mq_mode;\n \n-\tif (mq_mode & ETH_MQ_RX_DCB_FLAG) {\n-\t\tPMD_INIT_LOG(ERR, \"i40e doesn't support DCB yet\");\n-\t\treturn -ENOTSUP;\n-\t}\n-\n \t/* RSS setup */\n \tif (mq_mode & ETH_MQ_RX_RSS_FLAG)\n \t\tret = i40e_pf_config_rss(pf);\n@@ -6508,3 +6534,485 @@ i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,\n \n \treturn  0;\n }\n+\n+/*\n+ * i40e_parse_dcb_configure - parse dcb configure from user\n+ * @dev: the device being configured\n+ * @dcb_cfg: pointer of the result of parse\n+ * @*tc_map: bit map of enabled traffic classes\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static int\n+i40e_parse_dcb_configure(struct rte_eth_dev *dev,\n+\t\t\t struct i40e_dcbx_config *dcb_cfg,\n+\t\t\t uint8_t *tc_map)\n+{\n+\tstruct rte_eth_dcb_rx_conf *dcb_rx_conf;\n+\tuint8_t i, tc_bw, bw_lf;\n+\n+\tmemset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));\n+\n+\tdcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;\n+\tif (dcb_rx_conf->nb_tcs > I40E_MAX_TRAFFIC_CLASS) {\n+\t\tPMD_INIT_LOG(ERR, \"number of tc exceeds max.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* assume each tc has the same bw */\n+\ttc_bw = I40E_MAX_PERCENT / dcb_rx_conf->nb_tcs;\n+\tfor (i = 0; i < dcb_rx_conf->nb_tcs; i++)\n+\t\tdcb_cfg->etscfg.tcbwtable[i] = tc_bw;\n+\t/* to ensure the sum of tcbw is equal to 100 */\n+\tbw_lf = I40E_MAX_PERCENT % dcb_rx_conf->nb_tcs;\n+\tfor (i = 0; i < bw_lf; i++)\n+\t\tdcb_cfg->etscfg.tcbwtable[i]++;\n+\n+\t/* assume each tc has the same Transmission Selection Algorithm */\n+\tfor (i = 0; i < dcb_rx_conf->nb_tcs; i++)\n+\t\tdcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;\n+\n+\tfor (i = 0; i < I40E_MAX_USER_PRIORITY; i++)\n+\t\tdcb_cfg->etscfg.prioritytable[i] =\n+\t\t\t\tdcb_rx_conf->dcb_tc[i];\n+\n+\t/* FW needs one App to configure HW */\n+\tdcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;\n+\tdcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;\n+\tdcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;\n+\tdcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;\n+\n+\tif (dcb_rx_conf->nb_tcs == 0)\n+\t\t*tc_map = 1; /* tc0 only */\n+\telse\n+\t\t*tc_map = RTE_LEN2MASK(dcb_rx_conf->nb_tcs, uint8_t);\n+\n+\tif (dev->data->dev_conf.dcb_capability_en & ETH_DCB_PFC_SUPPORT) {\n+\t\tdcb_cfg->pfc.willing = 0;\n+\t\tdcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;\n+\t\tdcb_cfg->pfc.pfcenable = *tc_map;\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * i40e_vsi_get_bw_info - Query VSI BW Information\n+ * @vsi: the VSI being queried\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static int\n+i40e_vsi_get_bw_info(struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_aqc_query_vsi_ets_sla_config_resp bw_ets_config = {0};\n+\tstruct i40e_aqc_query_vsi_bw_config_resp bw_config = {0};\n+\tstruct i40e_hw *hw = I40E_VSI_TO_HW(vsi);\n+\tint i, ret;\n+\tuint32_t tc_bw_max;\n+\n+\t/* Get the VSI level BW configuration */\n+\tret = i40e_aq_query_vsi_bw_config(hw, vsi->seid, &bw_config, NULL);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"couldn't get PF vsi bw config, 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\treturn -EINVAL;\n+\t}\n+\n+\t/* Get the VSI level BW configuration per TC */\n+\tret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid, &bw_ets_config,\n+\t\t\t\t\t\t  NULL);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"couldn't get PF vsi ets bw config, 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\treturn -EINVAL;\n+\t}\n+\n+\tif (bw_config.tc_valid_bits != bw_ets_config.tc_valid_bits) {\n+\t\tPMD_INIT_LOG(WARNING,\n+\t\t\t \"Enabled TCs mismatch from querying VSI BW info\"\n+\t\t\t \" 0x%08x 0x%08x\\n\", bw_config.tc_valid_bits,\n+\t\t\t bw_ets_config.tc_valid_bits);\n+\t\t/* Still continuing */\n+\t}\n+\n+\tvsi->bw_info.bw_limit = rte_le_to_cpu_16(bw_config.port_bw_limit);\n+\tvsi->bw_info.bw_max_quanta = bw_config.max_bw;\n+\ttc_bw_max = rte_le_to_cpu_16(bw_ets_config.tc_bw_max[0]) |\n+\t\t    (rte_le_to_cpu_16(bw_ets_config.tc_bw_max[1]) << 16);\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tvsi->bw_info.bw_ets_share_credits[i] =\n+\t\t\t\tbw_ets_config.share_credits[i];\n+\t\tvsi->bw_info.bw_ets_limit_credits[i] =\n+\t\t\t\trte_le_to_cpu_16(bw_ets_config.credits[i]);\n+\t\t/* 3 bits out of 4 for each TC */\n+\t\tvsi->bw_info.bw_ets_max_quanta[i] =\n+\t\t\t(uint8_t)((tc_bw_max >> (i * 4)) & 0x7);\n+\t\tPMD_INIT_LOG(DEBUG,\n+\t\t\t \"%s: vsi seid = %d, TC = %d, qset = 0x%x\\n\",\n+\t\t\t __func__, vsi->seid, i, bw_config.qs_handles[i]);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+i40e_vsi_update_queue_mapping(struct i40e_vsi *vsi,\n+\t\t\t      struct i40e_aqc_vsi_properties_data *info,\n+\t\t\t      uint8_t enabled_tcmap)\n+{\n+\tint ret, i, total_tc = 0;\n+\tuint16_t qpnum_per_tc, bsf, qp_idx;\n+\tstruct rte_eth_dev_data *dev_data = I40E_VSI_TO_DEV_DATA(vsi);\n+\n+\tret = validate_tcmap_parameter(vsi, enabled_tcmap);\n+\tif (ret != I40E_SUCCESS)\n+\t\treturn ret;\n+\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tif (enabled_tcmap & (1 << i))\n+\t\t\ttotal_tc++;\n+\t}\n+\tif (total_tc == 0)\n+\t\ttotal_tc = 1;\n+\tvsi->enabled_tc = enabled_tcmap;\n+\n+\tqpnum_per_tc = dev_data->nb_rx_queues / total_tc;\n+\t/* Number of queues per enabled TC */\n+\tif (qpnum_per_tc == 0) {\n+\t\tPMD_INIT_LOG(ERR, \" number of queues is less that tcs.\");\n+\t\treturn I40E_ERR_INVALID_QP_ID;\n+\t}\n+\tqpnum_per_tc = RTE_MIN(i40e_align_floor(qpnum_per_tc),\n+\t\t\t\tI40E_MAX_Q_PER_TC);\n+\tbsf = rte_bsf32(qpnum_per_tc);\n+\n+\t/**\n+\t * Configure TC and queue mapping parameters, for enabled TC,\n+\t * allocate qpnum_per_tc queues to this traffic. For disabled TC,\n+\t * default queue will serve it.\n+\t */\n+\tqp_idx = 0;\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tif (vsi->enabled_tc & (1 << i)) {\n+\t\t\tinfo->tc_mapping[i] = rte_cpu_to_le_16((qp_idx <<\n+\t\t\t\t\tI40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |\n+\t\t\t\t(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));\n+\t\t\tqp_idx += qpnum_per_tc;\n+\t\t} else\n+\t\t\tinfo->tc_mapping[i] = 0;\n+\t}\n+\n+\t/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */\n+\tif (vsi->type == I40E_VSI_SRIOV) {\n+\t\tinfo->mapping_flags |=\n+\t\t\trte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);\n+\t\tfor (i = 0; i < vsi->nb_qps; i++)\n+\t\t\tinfo->queue_mapping[i] =\n+\t\t\t\trte_cpu_to_le_16(vsi->base_queue + i);\n+\t} else {\n+\t\tinfo->mapping_flags |=\n+\t\t\trte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);\n+\t\tinfo->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);\n+\t}\n+\tinfo->valid_sections |=\n+\t\trte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);\n+\n+\treturn I40E_SUCCESS;\n+}\n+\n+/*\n+ * i40e_vsi_config_tc - Configure VSI tc setting for given TC map\n+ * @vsi: VSI to be configured\n+ * @tc_map: enabled TC bitmap\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static int\n+i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 tc_map)\n+{\n+\tstruct i40e_aqc_configure_vsi_tc_bw_data bw_data;\n+\tstruct i40e_vsi_context ctxt;\n+\tstruct i40e_hw *hw = I40E_VSI_TO_HW(vsi);\n+\tint ret = 0;\n+\tint i;\n+\n+\t/* Check if enabled_tc is same as existing or new TCs */\n+\tif (vsi->enabled_tc == tc_map)\n+\t\treturn ret;\n+\n+\t/* configure tc bandwidth */\n+\tmemset(&bw_data, 0, sizeof(bw_data));\n+\tbw_data.tc_valid_bits = tc_map;\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 (tc_map & BIT_ULL(i))\n+\t\t\tbw_data.tc_bw_credits[i] = 1;\n+\t}\n+\tret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &bw_data, NULL);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"AQ command Config VSI BW allocation\"\n+\t\t\t\" per TC failed = %d\",\n+\t\t\thw->aq.asq_last_status);\n+\t\tgoto out;\n+\t}\n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)\n+\t\tvsi->info.qs_handle[i] = bw_data.qs_handles[i];\n+\n+\t/* Update Queue Pairs Mapping for currently enabled UPs */\n+\tctxt.seid = vsi->seid;\n+\tctxt.pf_num = hw->pf_id;\n+\tctxt.vf_num = 0;\n+\tctxt.uplink_seid = vsi->uplink_seid;\n+\tctxt.info = vsi->info;\n+\ti40e_get_cap(hw);\n+\tret = i40e_vsi_update_queue_mapping(vsi, &ctxt.info, tc_map);\n+\tif (ret)\n+\t\tgoto out;\n+\n+\t/* Update the VSI after updating the VSI queue-mapping information */\n+\tret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to configure \"\n+\t\t\t    \"TC queue mapping = %d\",\n+\t\t\t    hw->aq.asq_last_status);\n+\t\tgoto out;\n+\t}\n+\t/* update the local VSI info with updated queue map */\n+\t(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,\n+\t\t\t\t\tsizeof(vsi->info.tc_mapping));\n+\t(void)rte_memcpy(&vsi->info.queue_mapping,\n+\t\t\t&ctxt.info.queue_mapping,\n+\t\tsizeof(vsi->info.queue_mapping));\n+\tvsi->info.mapping_flags = ctxt.info.mapping_flags;\n+\tvsi->info.valid_sections = 0;\n+\n+\t/* Update current VSI BW information */\n+\tret = i40e_vsi_get_bw_info(vsi);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Failed updating vsi bw info, err %s aq_err %s\",\n+\t\t\t i40e_stat_str(hw, ret),\n+\t\t\t i40e_aq_str(hw, hw->aq.asq_last_status));\n+\t\tgoto out;\n+\t}\n+\n+\tvsi->enabled_tc = tc_map;\n+\n+out:\n+\treturn ret;\n+}\n+\n+/*\n+ * i40e_dcb_hw_configure - program the dcb setting to hw\n+ * @pf: pf the configuration is taken on\n+ * @new_cfg: new configuration\n+ * @tc_map: enabled TC bitmap\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static enum i40e_status_code\n+i40e_dcb_hw_configure(struct i40e_pf *pf,\n+\t\t      struct i40e_dcbx_config *new_cfg,\n+\t\t      uint8_t tc_map)\n+{\n+\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n+\tstruct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;\n+\tstruct i40e_vsi *main_vsi = pf->main_vsi;\n+\tstruct i40e_vsi_list *vsi_list;\n+\tint i, ret;\n+\tuint32_t val;\n+\n+\t/* Use the FW API if FW > v4.4*/\n+\tif (!((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver >= 4))) {\n+\t\tPMD_INIT_LOG(ERR, \"FW < v4.4, can not use FW LLDP API\"\n+\t\t\t\t  \" to configure DCB\");\n+\t\treturn I40E_ERR_FIRMWARE_API_VERSION;\n+\t}\n+\n+\t/* Check if need reconfiguration */\n+\tif (!memcmp(new_cfg, old_cfg, sizeof(struct i40e_dcbx_config))) {\n+\t\tPMD_INIT_LOG(ERR, \"No Change in DCB Config required.\");\n+\t\treturn I40E_SUCCESS;\n+\t}\n+\n+\t/* Copy the new config to the current config */\n+\t*old_cfg = *new_cfg;\n+\told_cfg->etsrec = old_cfg->etscfg;\n+\tret = i40e_set_dcb_config(hw);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR,\n+\t\t\t \"Set DCB Config failed, 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\treturn ret;\n+\t}\n+\t/* set receive Arbiter to RR mode and ETS scheme by default */\n+\tfor (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {\n+\t\tval = I40E_READ_REG(hw, I40E_PRTDCB_RETSTCC(i));\n+\t\tval &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK     |\n+\t\t\t I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |\n+\t\t\t I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);\n+\t\tval |= ((uint32_t)old_cfg->etscfg.tcbwtable[i] <<\n+\t\t\tI40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) &\n+\t\t\t I40E_PRTDCB_RETSTCC_BWSHARE_MASK;\n+\t\tval |= ((uint32_t)1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) &\n+\t\t\t I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK;\n+\t\tval |= ((uint32_t)1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) &\n+\t\t\t I40E_PRTDCB_RETSTCC_ETSTC_MASK;\n+\t\tI40E_WRITE_REG(hw, I40E_PRTDCB_RETSTCC(i), val);\n+\t}\n+\t/* get local mib to check whether it is configured correctly */\n+\t/* IEEE mode */\n+\thw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;\n+\t/* Get Local DCB Config */\n+\ti40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,\n+\t\t\t\t     &hw->local_dcbx_config);\n+\n+\t/* Update each VSI */\n+\ti40e_vsi_config_tc(main_vsi, tc_map);\n+\tif (main_vsi->veb) {\n+\t\tTAILQ_FOREACH(vsi_list, &main_vsi->veb->head, list) {\n+\t\t\t/* Beside main VSI, only enable default\n+\t\t\t * TC for other VSIs\n+\t\t\t */\n+\t\t\tret = i40e_vsi_config_tc(vsi_list->vsi,\n+\t\t\t\t\t\tI40E_DEFAULT_TCMAP);\n+\t\t\tif (ret)\n+\t\t\t\tPMD_INIT_LOG(WARNING,\n+\t\t\t\t\t \"Failed configuring TC for VSI seid=%d\\n\",\n+\t\t\t\t\t vsi_list->vsi->seid);\n+\t\t\t/* continue */\n+\t\t}\n+\t}\n+\treturn I40E_SUCCESS;\n+}\n+\n+/*\n+ * i40e_dcb_init_configure - initial dcb config\n+ * @dev: device being configured\n+ * @sw_dcb: indicate whether dcb is sw configured or hw offload\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static int\n+i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)\n+{\n+\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint ret = 0;\n+\n+\tif ((pf->flags & I40E_FLAG_DCB) == 0) {\n+\t\tPMD_INIT_LOG(ERR, \"HW doesn't support DCB\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\t/* DCB initialization:\n+\t * Update DCB configuration from the Firmware and configure\n+\t * LLDP MIB change event.\n+\t */\n+\tif (sw_dcb == TRUE) {\n+\t\tret = i40e_aq_stop_lldp(hw, TRUE, NULL);\n+\t\tif (ret != I40E_SUCCESS)\n+\t\t\tPMD_INIT_LOG(DEBUG, \"Failed to stop lldp\");\n+\n+\t\tret = i40e_init_dcb(hw);\n+\t\t/* if sw_dcb, lldp agent is stopped, the return from\n+\t\t * i40e_init_dcb we expect is failure with I40E_AQ_RC_EPERM\n+\t\t * adminq status.\n+\t\t */\n+\t\tif (ret != I40E_SUCCESS &&\n+\t\t    hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {\n+\t\t\tmemset(&hw->local_dcbx_config, 0,\n+\t\t\t\tsizeof(struct i40e_dcbx_config));\n+\t\t\t/* set dcb default configuration */\n+\t\t\thw->local_dcbx_config.etscfg.willing = 0;\n+\t\t\thw->local_dcbx_config.etscfg.maxtcs = 0;\n+\t\t\thw->local_dcbx_config.etscfg.tcbwtable[0] = 100;\n+\t\t\thw->local_dcbx_config.etscfg.tsatable[0] =\n+\t\t\t\t\t\tI40E_IEEE_TSA_ETS;\n+\t\t\thw->local_dcbx_config.etsrec =\n+\t\t\t\thw->local_dcbx_config.etscfg;\n+\t\t\thw->local_dcbx_config.pfc.willing = 0;\n+\t\t\thw->local_dcbx_config.pfc.pfccap =\n+\t\t\t\t\t\tI40E_MAX_TRAFFIC_CLASS;\n+\t\t\t/* FW needs one App to configure HW */\n+\t\t\thw->local_dcbx_config.numapps = 1;\n+\t\t\thw->local_dcbx_config.app[0].selector =\n+\t\t\t\t\t\tI40E_APP_SEL_ETHTYPE;\n+\t\t\thw->local_dcbx_config.app[0].priority = 3;\n+\t\t\thw->local_dcbx_config.app[0].protocolid =\n+\t\t\t\t\t\tI40E_APP_PROTOID_FCOE;\n+\t\t\tret = i40e_set_dcb_config(hw);\n+\t\t\tif (ret) {\n+\t\t\t\tPMD_INIT_LOG(ERR, \"default dcb config fails.\"\n+\t\t\t\t\t\" err = %d, aq_err = %d.\", ret,\n+\t\t\t\t\t  hw->aq.asq_last_status);\n+\t\t\t\treturn -ENOSYS;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tPMD_INIT_LOG(ERR, \"DCBX configuration failed, err = %d,\"\n+\t\t\t\t\t  \" aq_err = %d.\", ret,\n+\t\t\t\t\t  hw->aq.asq_last_status);\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\t} else {\n+\t\tret = i40e_aq_start_lldp(hw, NULL);\n+\t\tif (ret != I40E_SUCCESS)\n+\t\t\tPMD_INIT_LOG(DEBUG, \"Failed to start lldp\");\n+\n+\t\tret = i40e_init_dcb(hw);\n+\t\tif (!ret) {\n+\t\t\tif (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {\n+\t\t\t\tPMD_INIT_LOG(ERR, \"HW doesn't support\"\n+\t\t\t\t\t\t  \" DCBX offload.\");\n+\t\t\t\treturn -ENOTSUP;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tPMD_INIT_LOG(ERR, \"DCBX configuration failed, err = %d,\"\n+\t\t\t\t\t  \" aq_err = %d.\", ret,\n+\t\t\t\t\t  hw->aq.asq_last_status);\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * i40e_dcb_setup - setup dcb related config\n+ * @dev: device being configured\n+ *\n+ * Returns 0 on success, negative value on failure\n+ */\n+static int\n+i40e_dcb_setup(struct rte_eth_dev *dev)\n+{\n+\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tstruct i40e_dcbx_config dcb_cfg;\n+\tuint8_t tc_map = 0;\n+\tint ret = 0;\n+\n+\tif ((pf->flags & I40E_FLAG_DCB) == 0) {\n+\t\tPMD_INIT_LOG(ERR, \"HW doesn't support DCB\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (pf->vf_num != 0 ||\n+\t    (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG))\n+\t\tPMD_INIT_LOG(DEBUG, \" DCB only works on main vsi.\");\n+\n+\tret = i40e_parse_dcb_configure(dev, &dcb_cfg, &tc_map);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"invalid dcb config\");\n+\t\treturn -EINVAL;\n+\t}\n+\tret = i40e_dcb_hw_configure(pf, &dcb_cfg, tc_map);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"dcb sw configure fails\");\n+\t\treturn -ENOSYS;\n+\t}\n+\treturn 0;\n+}\ndiff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h\nindex 832c036..0c9c78c 100644\n--- a/drivers/net/i40e/i40e_ethdev.h\n+++ b/drivers/net/i40e/i40e_ethdev.h\n@@ -204,6 +204,19 @@ struct i40e_macvlan_filter {\n \tuint16_t vlan_id;\n };\n \n+/* Bandwidth limit information */\n+struct i40e_bw_info {\n+\tuint16_t bw_limit;      /* BW Limit (0 = disabled) */\n+\tuint8_t  bw_max_quanta; /* Max Quanta when BW limit is enabled */\n+\n+\t/* Relative TC credits across VSIs */\n+\tuint8_t  bw_ets_share_credits[I40E_MAX_TRAFFIC_CLASS];\n+\t/* TC BW limit credits within VSI */\n+\tuint8_t  bw_ets_limit_credits[I40E_MAX_TRAFFIC_CLASS];\n+\t/* TC BW limit max quanta within VSI */\n+\tuint8_t  bw_ets_max_quanta[I40E_MAX_TRAFFIC_CLASS];\n+};\n+\n /*\n  * Structure that defines a VSI, associated with a adapter.\n  */\n@@ -249,6 +262,7 @@ struct i40e_vsi {\n \tuint16_t vsi_id;\n \tuint16_t msix_intr; /* The MSIX interrupt binds to VSI */\n \tuint8_t enabled_tc; /* The traffic class enabled */\n+\tstruct i40e_bw_info bw_info; /* VSI bandwidth information */\n };\n \n struct pool_entry {\ndiff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c\nindex 8731712..e7af655 100644\n--- a/drivers/net/i40e/i40e_rxtx.c\n+++ b/drivers/net/i40e/i40e_rxtx.c\n@@ -2110,7 +2110,8 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,\n \tstruct i40e_rx_queue *rxq;\n \tconst struct rte_memzone *rz;\n \tuint32_t ring_size;\n-\tuint16_t len;\n+\tuint16_t len, i;\n+\tuint16_t base, bsf, tc_mapping;\n \tint use_def_burst_func = 1;\n \n \tif (hw->mac.type == I40E_MAC_VF) {\n@@ -2231,6 +2232,19 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,\n \t\tad->rx_bulk_alloc_allowed = false;\n \t}\n \n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tif (!(vsi->enabled_tc & (1 << i)))\n+\t\t\tcontinue;\n+\t\ttc_mapping = rte_le_to_cpu_16(vsi->info.tc_mapping[i]);\n+\t\tbase = (tc_mapping & I40E_AQ_VSI_TC_QUE_OFFSET_MASK) >>\n+\t\t\tI40E_AQ_VSI_TC_QUE_OFFSET_SHIFT;\n+\t\tbsf = (tc_mapping & I40E_AQ_VSI_TC_QUE_NUMBER_MASK) >>\n+\t\t\tI40E_AQ_VSI_TC_QUE_NUMBER_SHIFT;\n+\n+\t\tif (queue_idx >= base && queue_idx < (base + BIT(bsf)))\n+\t\t\trxq->dcb_tc = i;\n+\t}\n+\n \treturn 0;\n }\n \n@@ -2323,6 +2337,7 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,\n \tconst struct rte_memzone *tz;\n \tuint32_t ring_size;\n \tuint16_t tx_rs_thresh, tx_free_thresh;\n+\tuint16_t i, base, bsf, tc_mapping;\n \n \tif (hw->mac.type == I40E_MAC_VF) {\n \t\tstruct i40e_vf *vf =\n@@ -2492,6 +2507,19 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,\n \t/* Use a simple TX queue without offloads or multi segs if possible */\n \ti40e_set_tx_function_flag(dev, txq);\n \n+\tfor (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {\n+\t\tif (!(vsi->enabled_tc & (1 << i)))\n+\t\t\tcontinue;\n+\t\ttc_mapping = rte_le_to_cpu_16(vsi->info.tc_mapping[i]);\n+\t\tbase = (tc_mapping & I40E_AQ_VSI_TC_QUE_OFFSET_MASK) >>\n+\t\t\tI40E_AQ_VSI_TC_QUE_OFFSET_SHIFT;\n+\t\tbsf = (tc_mapping & I40E_AQ_VSI_TC_QUE_NUMBER_MASK) >>\n+\t\t\tI40E_AQ_VSI_TC_QUE_NUMBER_SHIFT;\n+\n+\t\tif (queue_idx >= base && queue_idx < (base + BIT(bsf)))\n+\t\t\ttxq->dcb_tc = i;\n+\t}\n+\n \treturn 0;\n }\n \n@@ -2704,7 +2732,7 @@ i40e_tx_queue_init(struct i40e_tx_queue *txq)\n #ifdef RTE_LIBRTE_IEEE1588\n \ttx_ctx.timesync_ena = 1;\n #endif\n-\ttx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[0]);\n+\ttx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[txq->dcb_tc]);\n \tif (vsi->type == I40E_VSI_FDIR)\n \t\ttx_ctx.fd_ena = TRUE;\n \ndiff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h\nindex 39cb95a..c35828c 100644\n--- a/drivers/net/i40e/i40e_rxtx.h\n+++ b/drivers/net/i40e/i40e_rxtx.h\n@@ -133,6 +133,7 @@ struct i40e_rx_queue {\n \tbool q_set; /**< indicate if rx queue has been configured */\n \tbool rx_deferred_start; /**< don't start this queue in dev start */\n \tuint16_t rx_using_sse; /**<flag indicate the usage of vPMD for rx */\n+\tuint8_t dcb_tc;         /**< Traffic class of rx queue */\n };\n \n struct i40e_tx_entry {\n@@ -173,6 +174,7 @@ struct i40e_tx_queue {\n \tuint16_t tx_next_rs;\n \tbool q_set; /**< indicate if tx queue has been configured */\n \tbool tx_deferred_start; /**< don't start this queue in dev start */\n+\tuint8_t dcb_tc;         /**< Traffic class of tx queue */\n };\n \n /** Offload features */\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "3/9"
    ]
}