get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 94860,
    "url": "https://patches.dpdk.org/api/patches/94860/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210625093157.24436-6-ting.xu@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": "<20210625093157.24436-6-ting.xu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210625093157.24436-6-ting.xu@intel.com",
    "date": "2021-06-25T09:31:57",
    "name": "[v3,5/5] net/iavf: query QoS cap and set queue TC mapping",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "f24108ca5cbc28a963b98595d236fc0a9f40d79c",
    "submitter": {
        "id": 1363,
        "url": "https://patches.dpdk.org/api/people/1363/?format=api",
        "name": "Xu, Ting",
        "email": "ting.xu@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210625093157.24436-6-ting.xu@intel.com/mbox/",
    "series": [
        {
            "id": 17486,
            "url": "https://patches.dpdk.org/api/series/17486/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=17486",
            "date": "2021-06-25T09:31:52",
            "name": "Enable ETS-based Tx QoS for VF in DCF",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/17486/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/94860/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/94860/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id C9738A0547;\n\tFri, 25 Jun 2021 11:34:06 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 37C71410F3;\n\tFri, 25 Jun 2021 11:33:45 +0200 (CEST)",
            "from mga17.intel.com (mga17.intel.com [192.55.52.151])\n by mails.dpdk.org (Postfix) with ESMTP id 361BB40E09\n for <dev@dpdk.org>; Fri, 25 Jun 2021 11:33:38 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 25 Jun 2021 02:33:35 -0700",
            "from dpdk-xuting-main.sh.intel.com ([10.67.117.76])\n by orsmga001.jf.intel.com with ESMTP; 25 Jun 2021 02:33:32 -0700"
        ],
        "IronPort-SDR": [
            "\n g0FVwYNJ6OpMqQZI5fbg0qcpV6VkpRHrtZyM1DVFBptFoqi+mfk2gbXu1ioybSTKBwHIiKegRg\n dhws84Tu26Rw==",
            "\n FgwjIemQvE/i9BIEt6MH890nkQ5MIMzyKesNjObI8EPxb8XnUMwFJogcsmfHylEiP8dqIc1kYC\n r6hxzONah9Tg=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10025\"; a=\"188022052\"",
            "E=Sophos;i=\"5.83,298,1616482800\"; d=\"scan'208\";a=\"188022052\"",
            "E=Sophos;i=\"5.83,298,1616482800\"; d=\"scan'208\";a=\"488117920\""
        ],
        "X-ExtLoop1": "1",
        "From": "Ting Xu <ting.xu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "qi.z.zhang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com,\n qiming.yang@intel.com",
        "Date": "Fri, 25 Jun 2021 17:31:57 +0800",
        "Message-Id": "<20210625093157.24436-6-ting.xu@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20210625093157.24436-1-ting.xu@intel.com>",
        "References": "<20210601014034.36100-1-ting.xu@intel.com>\n <20210625093157.24436-1-ting.xu@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v3 5/5] net/iavf: query QoS cap and set queue TC\n mapping",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch added the support for VF to config the ETS-based Tx QoS,\nincluding querying current QoS configuration from PF and config queue TC\nmapping. PF QoS is configured in advance and the queried info is\nprovided to the user for future usage. VF queues are mapped to different\nTCs in PF through virtchnl.\n\nSigned-off-by: Qiming Yang <qiming.yang@intel.com>\nSigned-off-by: Ting Xu <ting.xu@intel.com>\n---\n drivers/net/iavf/iavf.h        |  45 +++\n drivers/net/iavf/iavf_ethdev.c |  31 ++\n drivers/net/iavf/iavf_tm.c     | 667 +++++++++++++++++++++++++++++++++\n drivers/net/iavf/iavf_vchnl.c  |  56 ++-\n drivers/net/iavf/meson.build   |   1 +\n 5 files changed, 799 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/iavf/iavf_tm.c",
    "diff": "diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h\nindex 4f5811ae87..77ddf15f42 100644\n--- a/drivers/net/iavf/iavf.h\n+++ b/drivers/net/iavf/iavf.h\n@@ -6,6 +6,8 @@\n #define _IAVF_ETHDEV_H_\n \n #include <rte_kvargs.h>\n+#include <rte_tm_driver.h>\n+\n #include <iavf_prototype.h>\n #include <iavf_adminq_cmd.h>\n #include <iavf_type.h>\n@@ -82,6 +84,8 @@\n #define IAVF_RX_DESC_EXT_STATUS_FLEXBH_MASK  0x03\n #define IAVF_RX_DESC_EXT_STATUS_FLEXBH_FD_ID 0x01\n \n+#define IAVF_BITS_PER_BYTE 8\n+\n struct iavf_adapter;\n struct iavf_rx_queue;\n struct iavf_tx_queue;\n@@ -129,6 +133,38 @@ enum iavf_aq_result {\n \tIAVF_MSG_CMD,      /* Read async command result */\n };\n \n+/* Struct to store Traffic Manager node configuration. */\n+struct iavf_tm_node {\n+\tTAILQ_ENTRY(iavf_tm_node) node;\n+\tuint32_t id;\n+\tuint32_t tc;\n+\tuint32_t priority;\n+\tuint32_t weight;\n+\tuint32_t reference_count;\n+\tstruct iavf_tm_node *parent;\n+\tstruct rte_tm_node_params params;\n+};\n+\n+TAILQ_HEAD(iavf_tm_node_list, iavf_tm_node);\n+\n+/* node type of Traffic Manager */\n+enum iavf_tm_node_type {\n+\tIAVF_TM_NODE_TYPE_PORT,\n+\tIAVF_TM_NODE_TYPE_TC,\n+\tIAVF_TM_NODE_TYPE_QUEUE,\n+\tIAVF_TM_NODE_TYPE_MAX,\n+};\n+\n+/* Struct to store all the Traffic Manager configuration. */\n+struct iavf_tm_conf {\n+\tstruct iavf_tm_node *root; /* root node - vf vsi */\n+\tstruct iavf_tm_node_list tc_list; /* node list for all the TCs */\n+\tstruct iavf_tm_node_list queue_list; /* node list for all the queues */\n+\tuint32_t nb_tc_node;\n+\tuint32_t nb_queue_node;\n+\tbool committed;\n+};\n+\n /* Structure to store private data specific for VF instance. */\n struct iavf_info {\n \tuint16_t num_queue_pairs;\n@@ -175,6 +211,9 @@ struct iavf_info {\n \tstruct iavf_fdir_info fdir; /* flow director info */\n \t/* indicate large VF support enabled or not */\n \tbool lv_enabled;\n+\n+\tstruct virtchnl_qos_cap_list *qos_cap;\n+\tstruct iavf_tm_conf tm_conf;\n };\n \n #define IAVF_MAX_PKT_TYPE 1024\n@@ -344,4 +383,10 @@ int iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,\n \t\t\tuint32_t mc_addrs_num, bool add);\n int iavf_request_queues(struct iavf_adapter *adapter, uint16_t num);\n int iavf_get_max_rss_queue_region(struct iavf_adapter *adapter);\n+int iavf_get_qos_cap(struct iavf_adapter *adapter);\n+int iavf_set_q_tc_map(struct rte_eth_dev *dev,\n+\t\t\tstruct virtchnl_queue_tc_mapping *q_tc_mapping,\n+\t\t\tuint16_t size);\n+void iavf_tm_conf_init(struct rte_eth_dev *dev);\n+extern const struct rte_tm_ops iavf_tm_ops;\n #endif /* _IAVF_ETHDEV_H_ */\ndiff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c\nindex 5290588b17..c8ee1a834b 100644\n--- a/drivers/net/iavf/iavf_ethdev.c\n+++ b/drivers/net/iavf/iavf_ethdev.c\n@@ -122,6 +122,7 @@ static int iavf_dev_flow_ops_get(struct rte_eth_dev *dev,\n static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,\n \t\t\tstruct rte_ether_addr *mc_addrs,\n \t\t\tuint32_t mc_addrs_num);\n+static int iavf_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg);\n \n static const struct rte_pci_id pci_id_iavf_map[] = {\n \t{ RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },\n@@ -200,8 +201,21 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {\n \t.flow_ops_get               = iavf_dev_flow_ops_get,\n \t.tx_done_cleanup\t    = iavf_dev_tx_done_cleanup,\n \t.get_monitor_addr           = iavf_get_monitor_addr,\n+\t.tm_ops_get                 = iavf_tm_ops_get,\n };\n \n+static int\n+iavf_tm_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t\tvoid *arg)\n+{\n+\tif (!arg)\n+\t\treturn -EINVAL;\n+\n+\t*(const void **)arg = &iavf_tm_ops;\n+\n+\treturn 0;\n+}\n+\n static int\n iavf_set_mc_addr_list(struct rte_eth_dev *dev,\n \t\t\tstruct rte_ether_addr *mc_addrs,\n@@ -806,6 +820,11 @@ iavf_dev_start(struct rte_eth_dev *dev)\n \t\t\t\t      dev->data->nb_tx_queues);\n \tnum_queue_pairs = vf->num_queue_pairs;\n \n+\tif (iavf_get_qos_cap(adapter)) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to get qos capability\");\n+\t\treturn -1;\n+\t}\n+\n \tif (iavf_init_queues(dev) != 0) {\n \t\tPMD_DRV_LOG(ERR, \"failed to do Queue init\");\n \t\treturn -1;\n@@ -2090,6 +2109,15 @@ iavf_init_vf(struct rte_eth_dev *dev)\n \t\tPMD_INIT_LOG(ERR, \"unable to allocate vf_res memory\");\n \t\tgoto err_api;\n \t}\n+\n+\tbufsz = sizeof(struct virtchnl_qos_cap_list) +\n+\t\tIAVF_MAX_TRAFFIC_CLASS * sizeof(struct virtchnl_qos_cap_elem);\n+\tvf->qos_cap = rte_zmalloc(\"qos_cap\", bufsz, 0);\n+\tif (!vf->qos_cap) {\n+\t\tPMD_INIT_LOG(ERR, \"unable to allocate qos_cap memory\");\n+\t\tgoto err_api;\n+\t}\n+\n \tif (iavf_get_vf_resource(adapter) != 0) {\n \t\tPMD_INIT_LOG(ERR, \"iavf_get_vf_config failed\");\n \t\tgoto err_alloc;\n@@ -2131,6 +2159,7 @@ iavf_init_vf(struct rte_eth_dev *dev)\n \trte_free(vf->rss_key);\n \trte_free(vf->rss_lut);\n err_alloc:\n+\trte_free(vf->qos_cap);\n \trte_free(vf->vf_res);\n \tvf->vsi_res = NULL;\n err_api:\n@@ -2299,6 +2328,8 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)\n \n \tiavf_default_rss_disable(adapter);\n \n+\tiavf_tm_conf_init(eth_dev);\n+\n \treturn 0;\n }\n \ndiff --git a/drivers/net/iavf/iavf_tm.c b/drivers/net/iavf/iavf_tm.c\nnew file mode 100644\nindex 0000000000..0211fcc0a3\n--- /dev/null\n+++ b/drivers/net/iavf/iavf_tm.c\n@@ -0,0 +1,667 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2017 Intel Corporation\n+ */\n+#include <rte_tm_driver.h>\n+\n+#include \"iavf.h\"\n+\n+static int iavf_hierarchy_commit(struct rte_eth_dev *dev,\n+\t\t\t\t __rte_unused int clear_on_fail,\n+\t\t\t\t __rte_unused struct rte_tm_error *error);\n+static int iavf_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,\n+\t      uint32_t parent_node_id, uint32_t priority,\n+\t      uint32_t weight, uint32_t level_id,\n+\t      struct rte_tm_node_params *params,\n+\t      struct rte_tm_error *error);\n+static int iavf_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t\t    struct rte_tm_error *error);\n+static int iavf_tm_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t struct rte_tm_capabilities *cap,\n+\t\t\t struct rte_tm_error *error);\n+static int iavf_level_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t    uint32_t level_id,\n+\t\t\t    struct rte_tm_level_capabilities *cap,\n+\t\t\t    struct rte_tm_error *error);\n+static int iavf_node_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t\t      uint32_t node_id,\n+\t\t\t\t      struct rte_tm_node_capabilities *cap,\n+\t\t\t\t      struct rte_tm_error *error);\n+static int iavf_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t   int *is_leaf, struct rte_tm_error *error);\n+\n+const struct rte_tm_ops iavf_tm_ops = {\n+\t.node_add = iavf_tm_node_add,\n+\t.node_delete = iavf_tm_node_delete,\n+\t.capabilities_get = iavf_tm_capabilities_get,\n+\t.level_capabilities_get = iavf_level_capabilities_get,\n+\t.node_capabilities_get = iavf_node_capabilities_get,\n+\t.node_type_get = iavf_node_type_get,\n+\t.hierarchy_commit = iavf_hierarchy_commit,\n+};\n+\n+void\n+iavf_tm_conf_init(struct rte_eth_dev *dev)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\n+\t/* initialize node configuration */\n+\tvf->tm_conf.root = NULL;\n+\tTAILQ_INIT(&vf->tm_conf.tc_list);\n+\tTAILQ_INIT(&vf->tm_conf.queue_list);\n+\tvf->tm_conf.nb_tc_node = 0;\n+\tvf->tm_conf.nb_queue_node = 0;\n+\tvf->tm_conf.committed = false;\n+}\n+\n+\n+static inline struct iavf_tm_node *\n+iavf_tm_node_search(struct rte_eth_dev *dev,\n+\t\t    uint32_t node_id, enum iavf_tm_node_type *node_type)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tstruct iavf_tm_node_list *tc_list = &vf->tm_conf.tc_list;\n+\tstruct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;\n+\tstruct iavf_tm_node *tm_node;\n+\n+\tif (vf->tm_conf.root && vf->tm_conf.root->id == node_id) {\n+\t\t*node_type = IAVF_TM_NODE_TYPE_PORT;\n+\t\treturn vf->tm_conf.root;\n+\t}\n+\n+\tTAILQ_FOREACH(tm_node, tc_list, node) {\n+\t\tif (tm_node->id == node_id) {\n+\t\t\t*node_type = IAVF_TM_NODE_TYPE_TC;\n+\t\t\treturn tm_node;\n+\t\t}\n+\t}\n+\n+\tTAILQ_FOREACH(tm_node, queue_list, node) {\n+\t\tif (tm_node->id == node_id) {\n+\t\t\t*node_type = IAVF_TM_NODE_TYPE_QUEUE;\n+\t\t\treturn tm_node;\n+\t\t}\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int\n+iavf_node_param_check(struct iavf_info *vf, uint32_t node_id,\n+\t\t      uint32_t priority, uint32_t weight,\n+\t\t      struct rte_tm_node_params *params,\n+\t\t      struct rte_tm_error *error)\n+{\n+\t/* checked all the unsupported parameter */\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (priority) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;\n+\t\terror->message = \"priority should be 0\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (weight != 1) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;\n+\t\terror->message = \"weight must be 1\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* not support shaper profile */\n+\tif (params->shaper_profile_id) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;\n+\t\terror->message = \"shaper profile not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* not support shared shaper */\n+\tif (params->shared_shaper_id) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;\n+\t\terror->message = \"shared shaper not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->n_shared_shapers) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;\n+\t\terror->message = \"shared shaper not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* for non-leaf node */\n+\tif (node_id >= vf->num_queue_pairs) {\n+\t\tif (params->nonleaf.wfq_weight_mode) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;\n+\t\t\terror->message = \"WFQ not supported\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (params->nonleaf.n_sp_priorities != 1) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;\n+\t\t\terror->message = \"SP priority not supported\";\n+\t\t\treturn -EINVAL;\n+\t\t} else if (params->nonleaf.wfq_weight_mode &&\n+\t\t\t   !(*params->nonleaf.wfq_weight_mode)) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;\n+\t\t\terror->message = \"WFP should be byte mode\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* for leaf node */\n+\tif (params->leaf.cman) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;\n+\t\terror->message = \"Congestion management not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.wred_profile_id !=\n+\t    RTE_TM_WRED_PROFILE_ID_NONE) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.shared_wred_context_id) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.n_shared_wred_contexts) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t   int *is_leaf, struct rte_tm_error *error)\n+{\n+\tenum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;\n+\tstruct iavf_tm_node *tm_node;\n+\n+\tif (!is_leaf || !error)\n+\t\treturn -EINVAL;\n+\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check if the node id exists */\n+\ttm_node = iavf_tm_node_search(dev, node_id, &node_type);\n+\tif (!tm_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"no such node\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (node_type == IAVF_TM_NODE_TYPE_QUEUE)\n+\t\t*is_leaf = true;\n+\telse\n+\t\t*is_leaf = false;\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,\n+\t      uint32_t parent_node_id, uint32_t priority,\n+\t      uint32_t weight, uint32_t level_id,\n+\t      struct rte_tm_node_params *params,\n+\t      struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tenum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;\n+\tenum iavf_tm_node_type parent_node_type = IAVF_TM_NODE_TYPE_MAX;\n+\tstruct iavf_tm_node *tm_node;\n+\tstruct iavf_tm_node *parent_node;\n+\tuint16_t tc_nb = vf->qos_cap->num_elem;\n+\tint ret;\n+\n+\tif (!params || !error)\n+\t\treturn -EINVAL;\n+\n+\t/* if already committed */\n+\tif (vf->tm_conf.committed) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;\n+\t\terror->message = \"already committed\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = iavf_node_param_check(vf, node_id, priority, weight,\n+\t\t\t\t    params, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* check if the node is already existed */\n+\tif (iavf_tm_node_search(dev, node_id, &node_type)) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"node id already used\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* root node if not have a parent */\n+\tif (parent_node_id == RTE_TM_NODE_ID_NULL) {\n+\t\t/* check level */\n+\t\tif (level_id != IAVF_TM_NODE_TYPE_PORT) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\t\terror->message = \"Wrong level\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* obviously no more than one root */\n+\t\tif (vf->tm_conf.root) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\t\terror->message = \"already have a root\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* add the root node */\n+\t\ttm_node = rte_zmalloc(\"iavf_tm_node\",\n+\t\t\t\t      sizeof(struct iavf_tm_node),\n+\t\t\t\t      0);\n+\t\tif (!tm_node)\n+\t\t\treturn -ENOMEM;\n+\t\ttm_node->id = node_id;\n+\t\ttm_node->parent = NULL;\n+\t\ttm_node->reference_count = 0;\n+\t\trte_memcpy(&tm_node->params, params,\n+\t\t\t\t sizeof(struct rte_tm_node_params));\n+\t\tvf->tm_conf.root = tm_node;\n+\t\treturn 0;\n+\t}\n+\n+\t/* TC or queue node */\n+\t/* check the parent node */\n+\tparent_node = iavf_tm_node_search(dev, parent_node_id,\n+\t\t\t\t\t  &parent_node_type);\n+\tif (!parent_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\terror->message = \"parent not exist\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (parent_node_type != IAVF_TM_NODE_TYPE_PORT &&\n+\t    parent_node_type != IAVF_TM_NODE_TYPE_TC) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\terror->message = \"parent is not root or TC\";\n+\t\treturn -EINVAL;\n+\t}\n+\t/* check level */\n+\tif (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&\n+\t    level_id != parent_node_type + 1) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\terror->message = \"Wrong level\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check the node number */\n+\tif (parent_node_type == IAVF_TM_NODE_TYPE_PORT) {\n+\t\t/* check the TC number */\n+\t\tif (vf->tm_conf.nb_tc_node >= tc_nb) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too many TCs\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\t/* check the queue number */\n+\t\tif (parent_node->reference_count >= vf->num_queue_pairs) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too many queues\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (node_id >= vf->num_queue_pairs) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too large queue id\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\t/* add the TC or queue node */\n+\ttm_node = rte_zmalloc(\"iavf_tm_node\",\n+\t\t\t      sizeof(struct iavf_tm_node),\n+\t\t\t      0);\n+\tif (!tm_node)\n+\t\treturn -ENOMEM;\n+\ttm_node->id = node_id;\n+\ttm_node->reference_count = 0;\n+\ttm_node->parent = parent_node;\n+\trte_memcpy(&tm_node->params, params,\n+\t\t\t sizeof(struct rte_tm_node_params));\n+\tif (parent_node_type == IAVF_TM_NODE_TYPE_PORT) {\n+\t\tTAILQ_INSERT_TAIL(&vf->tm_conf.tc_list,\n+\t\t\t\t  tm_node, node);\n+\t\ttm_node->tc = vf->tm_conf.nb_tc_node;\n+\t\tvf->tm_conf.nb_tc_node++;\n+\t} else {\n+\t\tTAILQ_INSERT_TAIL(&vf->tm_conf.queue_list,\n+\t\t\t\t  tm_node, node);\n+\t\ttm_node->tc = parent_node->tc;\n+\t\tvf->tm_conf.nb_queue_node++;\n+\t}\n+\ttm_node->parent->reference_count++;\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tenum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;\n+\tstruct iavf_tm_node *tm_node;\n+\n+\tif (!error)\n+\t\treturn -EINVAL;\n+\n+\t/* if already committed */\n+\tif (vf->tm_conf.committed) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;\n+\t\terror->message = \"already committed\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check if the node id exists */\n+\ttm_node = iavf_tm_node_search(dev, node_id, &node_type);\n+\tif (!tm_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"no such node\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* the node should have no child */\n+\tif (tm_node->reference_count) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message =\n+\t\t\t\"cannot delete a node which has children\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* root node */\n+\tif (node_type == IAVF_TM_NODE_TYPE_PORT) {\n+\t\trte_free(tm_node);\n+\t\tvf->tm_conf.root = NULL;\n+\t\treturn 0;\n+\t}\n+\n+\t/* TC or queue node */\n+\ttm_node->parent->reference_count--;\n+\tif (node_type == IAVF_TM_NODE_TYPE_TC) {\n+\t\tTAILQ_REMOVE(&vf->tm_conf.tc_list, tm_node, node);\n+\t\tvf->tm_conf.nb_tc_node--;\n+\t} else {\n+\t\tTAILQ_REMOVE(&vf->tm_conf.queue_list, tm_node, node);\n+\t\tvf->tm_conf.nb_queue_node--;\n+\t}\n+\trte_free(tm_node);\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_tm_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t struct rte_tm_capabilities *cap,\n+\t\t\t struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tuint16_t tc_nb = vf->qos_cap->num_elem;\n+\n+\tif (!cap || !error)\n+\t\treturn -EINVAL;\n+\n+\tif (tc_nb > vf->vf_res->num_queue_pairs)\n+\t\treturn -EINVAL;\n+\n+\terror->type = RTE_TM_ERROR_TYPE_NONE;\n+\n+\t/* set all the parameters to 0 first. */\n+\tmemset(cap, 0, sizeof(struct rte_tm_capabilities));\n+\n+\t/**\n+\t * support port + TCs + queues\n+\t * here shows the max capability not the current configuration.\n+\t */\n+\tcap->n_nodes_max = 1 + IAVF_MAX_TRAFFIC_CLASS\n+\t\t+ vf->num_queue_pairs;\n+\tcap->n_levels_max = 3; /* port, TC, queue */\n+\tcap->non_leaf_nodes_identical = 1;\n+\tcap->leaf_nodes_identical = 1;\n+\tcap->shaper_n_max = cap->n_nodes_max;\n+\tcap->shaper_private_n_max = cap->n_nodes_max;\n+\tcap->shaper_private_dual_rate_n_max = 0;\n+\tcap->shaper_private_rate_min = 0;\n+\t/* GBps */\n+\tcap->shaper_private_rate_max =\n+\t\tvf->link_speed * 1000 / IAVF_BITS_PER_BYTE;\n+\tcap->shaper_private_packet_mode_supported = 0;\n+\tcap->shaper_private_byte_mode_supported = 1;\n+\tcap->shaper_shared_n_max = 0;\n+\tcap->shaper_shared_n_nodes_per_shaper_max = 0;\n+\tcap->shaper_shared_n_shapers_per_node_max = 0;\n+\tcap->shaper_shared_dual_rate_n_max = 0;\n+\tcap->shaper_shared_rate_min = 0;\n+\tcap->shaper_shared_rate_max = 0;\n+\tcap->shaper_shared_packet_mode_supported = 0;\n+\tcap->shaper_shared_byte_mode_supported = 0;\n+\tcap->sched_n_children_max = vf->num_queue_pairs;\n+\tcap->sched_sp_n_priorities_max = 1;\n+\tcap->sched_wfq_n_children_per_group_max = 0;\n+\tcap->sched_wfq_n_groups_max = 0;\n+\tcap->sched_wfq_weight_max = 1;\n+\tcap->sched_wfq_packet_mode_supported = 0;\n+\tcap->sched_wfq_byte_mode_supported = 0;\n+\tcap->cman_head_drop_supported = 0;\n+\tcap->dynamic_update_mask = 0;\n+\tcap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;\n+\tcap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\tcap->cman_wred_context_n_max = 0;\n+\tcap->cman_wred_context_private_n_max = 0;\n+\tcap->cman_wred_context_shared_n_max = 0;\n+\tcap->cman_wred_context_shared_n_nodes_per_context_max = 0;\n+\tcap->cman_wred_context_shared_n_contexts_per_node_max = 0;\n+\tcap->stats_mask = 0;\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_level_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t    uint32_t level_id,\n+\t\t\t    struct rte_tm_level_capabilities *cap,\n+\t\t\t    struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\n+\tif (!cap || !error)\n+\t\treturn -EINVAL;\n+\n+\tif (level_id >= IAVF_TM_NODE_TYPE_MAX) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_LEVEL_ID;\n+\t\terror->message = \"too deep level\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* root node */\n+\tif (level_id == IAVF_TM_NODE_TYPE_PORT) {\n+\t\tcap->n_nodes_max = 1;\n+\t\tcap->n_nodes_nonleaf_max = 1;\n+\t\tcap->n_nodes_leaf_max = 0;\n+\t} else if (level_id == IAVF_TM_NODE_TYPE_TC) {\n+\t\t/* TC */\n+\t\tcap->n_nodes_max = IAVF_MAX_TRAFFIC_CLASS;\n+\t\tcap->n_nodes_nonleaf_max = IAVF_MAX_TRAFFIC_CLASS;\n+\t\tcap->n_nodes_leaf_max = 0;\n+\t} else {\n+\t\t/* queue */\n+\t\tcap->n_nodes_max = vf->num_queue_pairs;\n+\t\tcap->n_nodes_nonleaf_max = 0;\n+\t\tcap->n_nodes_leaf_max = vf->num_queue_pairs;\n+\t}\n+\n+\tcap->non_leaf_nodes_identical = true;\n+\tcap->leaf_nodes_identical = true;\n+\n+\tif (level_id != IAVF_TM_NODE_TYPE_QUEUE) {\n+\t\tcap->nonleaf.shaper_private_supported = true;\n+\t\tcap->nonleaf.shaper_private_dual_rate_supported = false;\n+\t\tcap->nonleaf.shaper_private_rate_min = 0;\n+\t\t/* GBps */\n+\t\tcap->nonleaf.shaper_private_rate_max =\n+\t\t\tvf->link_speed * 1000 / IAVF_BITS_PER_BYTE;\n+\t\tcap->nonleaf.shaper_private_packet_mode_supported = 0;\n+\t\tcap->nonleaf.shaper_private_byte_mode_supported = 1;\n+\t\tcap->nonleaf.shaper_shared_n_max = 0;\n+\t\tcap->nonleaf.shaper_shared_packet_mode_supported = 0;\n+\t\tcap->nonleaf.shaper_shared_byte_mode_supported = 0;\n+\t\tif (level_id == IAVF_TM_NODE_TYPE_PORT)\n+\t\t\tcap->nonleaf.sched_n_children_max =\n+\t\t\t\tIAVF_MAX_TRAFFIC_CLASS;\n+\t\telse\n+\t\t\tcap->nonleaf.sched_n_children_max =\n+\t\t\t\tvf->num_queue_pairs;\n+\t\tcap->nonleaf.sched_sp_n_priorities_max = 1;\n+\t\tcap->nonleaf.sched_wfq_n_children_per_group_max = 0;\n+\t\tcap->nonleaf.sched_wfq_n_groups_max = 0;\n+\t\tcap->nonleaf.sched_wfq_weight_max = 1;\n+\t\tcap->nonleaf.sched_wfq_packet_mode_supported = 0;\n+\t\tcap->nonleaf.sched_wfq_byte_mode_supported = 0;\n+\t\tcap->nonleaf.stats_mask = 0;\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* queue node */\n+\tcap->leaf.shaper_private_supported = false;\n+\tcap->leaf.shaper_private_dual_rate_supported = false;\n+\tcap->leaf.shaper_private_rate_min = 0;\n+\t/* GBps */\n+\tcap->leaf.shaper_private_rate_max =\n+\t\tvf->link_speed * 1000 / IAVF_BITS_PER_BYTE;\n+\tcap->leaf.shaper_private_packet_mode_supported = 0;\n+\tcap->leaf.shaper_private_byte_mode_supported = 1;\n+\tcap->leaf.shaper_shared_n_max = 0;\n+\tcap->leaf.shaper_shared_packet_mode_supported = 0;\n+\tcap->leaf.shaper_shared_byte_mode_supported = 0;\n+\tcap->leaf.cman_head_drop_supported = false;\n+\tcap->leaf.cman_wred_context_private_supported = true;\n+\tcap->leaf.cman_wred_context_shared_n_max = 0;\n+\tcap->leaf.stats_mask = 0;\n+\n+\treturn 0;\n+}\n+\n+static int\n+iavf_node_capabilities_get(struct rte_eth_dev *dev,\n+\t\t\t   uint32_t node_id,\n+\t\t\t   struct rte_tm_node_capabilities *cap,\n+\t\t\t   struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tenum iavf_tm_node_type node_type;\n+\tstruct virtchnl_qos_cap_elem tc_cap;\n+\tstruct iavf_tm_node *tm_node;\n+\n+\tif (!cap || !error)\n+\t\treturn -EINVAL;\n+\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check if the node id exists */\n+\ttm_node = iavf_tm_node_search(dev, node_id, &node_type);\n+\tif (!tm_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"no such node\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (node_type != IAVF_TM_NODE_TYPE_TC) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\terror->message = \"not support capability get\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\ttc_cap = vf->qos_cap->cap[tm_node->tc];\n+\tif (tc_cap.tc_num != tm_node->tc) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\terror->message = \"tc not match\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcap->shaper_private_supported = true;\n+\tcap->shaper_private_dual_rate_supported = false;\n+\tcap->shaper_private_rate_min = tc_cap.shaper.committed;\n+\tcap->shaper_private_rate_max = tc_cap.shaper.peak;\n+\tcap->shaper_shared_n_max = 0;\n+\tcap->nonleaf.sched_n_children_max = vf->num_queue_pairs;\n+\tcap->nonleaf.sched_sp_n_priorities_max = 1;\n+\tcap->nonleaf.sched_wfq_n_children_per_group_max = 1;\n+\tcap->nonleaf.sched_wfq_n_groups_max = 0;\n+\tcap->nonleaf.sched_wfq_weight_max = tc_cap.weight;\n+\tcap->stats_mask = 0;\n+\n+\treturn 0;\n+}\n+\n+static int iavf_hierarchy_commit(struct rte_eth_dev *dev,\n+\t\t\t\t __rte_unused int clear_on_fail,\n+\t\t\t\t __rte_unused struct rte_tm_error *error)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tstruct virtchnl_queue_tc_mapping *q_tc_mapping;\n+\tstruct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;\n+\tstruct iavf_tm_node *tm_node;\n+\tuint16_t size;\n+\tint index = 0, node_committed = 0;\n+\tint ret, i;\n+\n+\tsize = sizeof(*q_tc_mapping) + sizeof(q_tc_mapping->tc[0]) *\n+\t\t(vf->qos_cap->num_elem - 1);\n+\tq_tc_mapping = rte_zmalloc(\"q_tc\", size, 0);\n+\tq_tc_mapping->vsi_id = vf->vsi.vsi_id;\n+\tq_tc_mapping->num_tc = vf->qos_cap->num_elem;\n+\tq_tc_mapping->num_queue_pairs = vf->num_queue_pairs;\n+\tTAILQ_FOREACH(tm_node, queue_list, node) {\n+\t\tif (tm_node->tc >= q_tc_mapping->num_tc) {\n+\t\t\tPMD_DRV_LOG(ERR, \"TC%d is not enabled\", tm_node->tc);\n+\t\t\treturn IAVF_ERR_PARAM;\n+\t\t}\n+\t\tq_tc_mapping->tc[tm_node->tc].req.queue_count++;\n+\t\tnode_committed++;\n+\t}\n+\n+\tfor (i = 0; i < IAVF_MAX_TRAFFIC_CLASS; i++) {\n+\t\tq_tc_mapping->tc[i].req.start_queue_id = index;\n+\t\tindex += q_tc_mapping->tc[i].req.queue_count;\n+\t}\n+\tif (node_committed < vf->num_queue_pairs) {\n+\t\tPMD_DRV_LOG(ERR, \"queue node is less than allocated queue pairs\");\n+\t\treturn IAVF_ERR_PARAM;\n+\t}\n+\n+\tret = iavf_set_q_tc_map(dev, q_tc_mapping, size);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn IAVF_SUCCESS;\n+}\ndiff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c\nindex 02e828f9b7..06dc663947 100644\n--- a/drivers/net/iavf/iavf_vchnl.c\n+++ b/drivers/net/iavf/iavf_vchnl.c\n@@ -467,7 +467,8 @@ iavf_get_vf_resource(struct iavf_adapter *adapter)\n \t\tVIRTCHNL_VF_OFFLOAD_REQ_QUEUES |\n \t\tVIRTCHNL_VF_OFFLOAD_CRC |\n \t\tVIRTCHNL_VF_OFFLOAD_VLAN_V2 |\n-\t\tVIRTCHNL_VF_LARGE_NUM_QPAIRS;\n+\t\tVIRTCHNL_VF_LARGE_NUM_QPAIRS |\n+\t\tVIRTCHNL_VF_OFFLOAD_QOS;\n \n \targs.in_args = (uint8_t *)&caps;\n \targs.in_args_size = sizeof(caps);\n@@ -1550,6 +1551,59 @@ iavf_set_hena(struct iavf_adapter *adapter, uint64_t hena)\n \treturn err;\n }\n \n+int\n+iavf_get_qos_cap(struct iavf_adapter *adapter)\n+{\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);\n+\tstruct iavf_cmd_info args;\n+\tuint32_t len;\n+\tint err;\n+\n+\targs.ops = VIRTCHNL_OP_GET_QOS_CAPS;\n+\targs.in_args = NULL;\n+\targs.in_args_size = 0;\n+\targs.out_buffer = vf->aq_resp;\n+\targs.out_size = IAVF_AQ_BUF_SZ;\n+\terr = iavf_execute_vf_cmd(adapter, &args);\n+\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Failed to execute command of OP_GET_VF_RESOURCE\");\n+\t\treturn -1;\n+\t}\n+\n+\tlen =  sizeof(struct virtchnl_qos_cap_list) +\n+\t\tIAVF_MAX_TRAFFIC_CLASS * sizeof(struct virtchnl_qos_cap_elem);\n+\n+\trte_memcpy(vf->qos_cap, args.out_buffer,\n+\t\t   RTE_MIN(args.out_size, len));\n+\n+\treturn 0;\n+}\n+\n+int iavf_set_q_tc_map(struct rte_eth_dev *dev,\n+\t\tstruct virtchnl_queue_tc_mapping *q_tc_mapping, uint16_t size)\n+{\n+\tstruct iavf_adapter *adapter =\n+\t\t\tIAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);\n+\tstruct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);\n+\tstruct iavf_cmd_info args;\n+\tint err;\n+\n+\tmemset(&args, 0, sizeof(args));\n+\targs.ops = VIRTCHNL_OP_CONFIG_QUEUE_TC_MAP;\n+\targs.in_args = (uint8_t *)q_tc_mapping;\n+\targs.in_args_size = size;\n+\targs.out_buffer = vf->aq_resp;\n+\targs.out_size = IAVF_AQ_BUF_SZ;\n+\n+\terr = iavf_execute_vf_cmd(adapter, &args);\n+\tif (err)\n+\t\tPMD_DRV_LOG(ERR, \"Failed to execute command of\"\n+\t\t\t    \" VIRTCHNL_OP_CONFIG_TC_MAP\");\n+\treturn err;\n+}\n+\n int\n iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,\n \t\t\tstruct rte_ether_addr *mc_addrs,\ndiff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build\nindex 6f222a9e87..f2010a8337 100644\n--- a/drivers/net/iavf/meson.build\n+++ b/drivers/net/iavf/meson.build\n@@ -19,6 +19,7 @@ sources = files(\n         'iavf_generic_flow.c',\n         'iavf_fdir.c',\n         'iavf_hash.c',\n+        'iavf_tm.c',\n )\n \n if arch_subdir == 'x86'\n",
    "prefixes": [
        "v3",
        "5/5"
    ]
}