get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 66401,
    "url": "http://patches.dpdk.org/api/patches/66401/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200309093243.63204-3-huwei013@chinasoftinc.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20200309093243.63204-3-huwei013@chinasoftinc.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200309093243.63204-3-huwei013@chinasoftinc.com",
    "date": "2020-03-09T09:32:40",
    "name": "[v2,2/5] net/hns3: fix wrong Tx interrupt when enabling Rx interrupt",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "7a4343b5ba9ede00165d685bd22e5ce76f22d2b4",
    "submitter": {
        "id": 1537,
        "url": "http://patches.dpdk.org/api/people/1537/?format=api",
        "name": "Wei Hu (Xavier)",
        "email": "huwei013@chinasoftinc.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200309093243.63204-3-huwei013@chinasoftinc.com/mbox/",
    "series": [
        {
            "id": 8836,
            "url": "http://patches.dpdk.org/api/series/8836/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8836",
            "date": "2020-03-09T09:32:39",
            "name": "misc updates and fixes for hns3 PMD driver",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/8836/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/66401/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/66401/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 58DFCA052E;\n\tMon,  9 Mar 2020 10:33:46 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 0E3A91C067;\n\tMon,  9 Mar 2020 10:33:26 +0100 (CET)",
            "from incedge.chinasoftinc.com (unknown [114.113.233.8])\n by dpdk.org (Postfix) with ESMTP id DC5F31C010\n for <dev@dpdk.org>; Mon,  9 Mar 2020 10:33:20 +0100 (CET)",
            "from mail.chinasoftinc.com (inccas001.ito.icss [10.168.0.51]) by\n incedge.chinasoftinc.com with ESMTP id kADETAa84LT2kuWK (version=TLSv1\n cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for <dev@dpdk.org>;\n Mon, 09 Mar 2020 17:32:49 +0800 (CST)",
            "from localhost.localdomain (114.119.4.74) by INCCAS001.ito.icss\n (10.168.0.60) with Microsoft SMTP Server id 14.3.487.0; Mon, 9 Mar 2020\n 17:32:49 +0800"
        ],
        "X-ASG-Debug-ID": "1583746368-0a3dd1404a03530003-TfluYd",
        "X-Barracuda-Envelope-From": "huwei013@chinasoftinc.com",
        "X-Barracuda-RBL-Trusted-Forwarder": [
            "10.168.0.51",
            "10.168.0.60"
        ],
        "X-ASG-Whitelist": "Client",
        "From": "\"Wei Hu (Xavier)\" <huwei013@chinasoftinc.com>",
        "To": "<dev@dpdk.org>",
        "Date": "Mon, 9 Mar 2020 17:32:40 +0800",
        "X-ASG-Orig-Subj": "[PATCH v2 2/5] net/hns3: fix wrong Tx interrupt when enabling\n Rx interrupt",
        "Message-ID": "<20200309093243.63204-3-huwei013@chinasoftinc.com>",
        "X-Mailer": "git-send-email 2.23.0",
        "In-Reply-To": "<20200309093243.63204-1-huwei013@chinasoftinc.com>",
        "References": "<20200309093243.63204-1-huwei013@chinasoftinc.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[114.119.4.74]",
        "X-Barracuda-Connect": "inccas001.ito.icss[10.168.0.51]",
        "X-Barracuda-Start-Time": "1583746369",
        "X-Barracuda-Encrypted": "ECDHE-RSA-AES256-SHA",
        "X-Barracuda-URL": "https://incspam.chinasofti.com:443/cgi-mod/mark.cgi",
        "X-Virus-Scanned": "by bsmtpd at chinasoftinc.com",
        "X-Barracuda-Scan-Msg-Size": "23715",
        "Subject": "[dpdk-dev] [PATCH v2 2/5] net/hns3: fix wrong Tx interrupt when\n\tenabling Rx interrupt",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "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": "From: \"Wei Hu (Xavier)\" <xavier.huwei@huawei.com>\n\nCurrently, when receiving and transmitting packets based on hns3 network\nengine there are probably unexpected and redundant Tx interrupts if Rx\ninterrupt is enabled.\n\nThe root cause as below:\nTx and Rx queues with the same number share the interrupt vector in hns3\nnetwork engine, and in this case there are the residual hardware mapping\nrelationship configuration between queue and interrupt vector configured\nin hns3 kernel ethdev driver.\n\nWe should clear the all hardware mapping relationship configrations in the\ninitialization. Because of the hardware constraints, we have to implement\nclearing the relationship by binding all queues to the last interrupt\nvector and reserving the last interrupt vector, this method results in a\ndecrease of the maximum queues when upper applications call the\nrte_eth_dev_configure API function to enable Rx interrupt.\n\nFixes: 02a7b55657b2 (\"net/hns3: support Rx interrupt\")\n\nSigned-off-by: Hao Chen <chenhao164@huawei.com>\nSigned-off-by: Chengwen Feng <fengchengwen@huawei.com>\nSigned-off-by: Lijun Ou <oulijun@huawei.com>\nSigned-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>\n---\n drivers/net/hns3/hns3_cmd.h       |  31 +++--\n drivers/net/hns3/hns3_ethdev.c    | 117 ++++++++++++++++---\n drivers/net/hns3/hns3_ethdev.h    |   1 +\n drivers/net/hns3/hns3_ethdev_vf.c | 180 ++++++++++++++++++++++++------\n drivers/net/hns3/hns3_regs.h      |  13 ++-\n drivers/net/hns3/hns3_rxtx.c      |  48 ++++++--\n drivers/net/hns3/hns3_rxtx.h      |   5 +-\n 7 files changed, 326 insertions(+), 69 deletions(-)",
    "diff": "diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h\nindex 897dc1420..26d410396 100644\n--- a/drivers/net/hns3/hns3_cmd.h\n+++ b/drivers/net/hns3/hns3_cmd.h\n@@ -79,6 +79,7 @@ enum hns3_opcode_type {\n \tHNS3_OPC_GBL_RST_STATUS         = 0x0021,\n \tHNS3_OPC_QUERY_FUNC_STATUS      = 0x0022,\n \tHNS3_OPC_QUERY_PF_RSRC          = 0x0023,\n+\tHNS3_OPC_QUERY_VF_RSRC          = 0x0024,\n \tHNS3_OPC_GET_CFG_PARAM          = 0x0025,\n \tHNS3_OPC_PF_RST_DONE            = 0x0026,\n \n@@ -337,8 +338,9 @@ struct hns3_func_status_cmd {\n \tuint8_t rsv[2];\n };\n \n-#define HNS3_PF_VEC_NUM_S\t\t0\n-#define HNS3_PF_VEC_NUM_M\t\tGENMASK(7, 0)\n+#define HNS3_VEC_NUM_S\t\t0\n+#define HNS3_VEC_NUM_M\t\tGENMASK(7, 0)\n+#define HNS3_MIN_VECTOR_NUM\t2 /* one for msi-x, another for IO */\n struct hns3_pf_res_cmd {\n \tuint16_t tqp_num;\n \tuint16_t buf_size;\n@@ -351,6 +353,15 @@ struct hns3_pf_res_cmd {\n \tuint32_t rsv[2];\n };\n \n+struct hns3_vf_res_cmd {\n+\tuint16_t tqp_num;\n+\tuint16_t reserved;\n+\tuint16_t msixcap_localid_ba_nic;\n+\tuint16_t msixcap_localid_ba_rocee;\n+\tuint16_t vf_intr_vector_number;\n+\tuint16_t rsv[7];\n+};\n+\n #define HNS3_UMV_SPC_ALC_B\t0\n struct hns3_umv_spc_alc_cmd {\n \tuint8_t allocate;\n@@ -677,13 +688,19 @@ struct hns3_tqp_map_cmd {\n \tuint8_t rsv[18];\n };\n \n-#define HNS3_RING_TYPE_B\t0\n-#define HNS3_RING_TYPE_TX\t0\n-#define HNS3_RING_TYPE_RX\t1\n+enum hns3_ring_type {\n+\tHNS3_RING_TYPE_TX,\n+\tHNS3_RING_TYPE_RX\n+};\n+\n+enum hns3_int_gl_idx {\n+\tHNS3_RING_GL_RX,\n+\tHNS3_RING_GL_TX,\n+\tHNS3_RING_GL_IMMEDIATE = 3\n+};\n+\n #define HNS3_RING_GL_IDX_S\t0\n #define HNS3_RING_GL_IDX_M\tGENMASK(1, 0)\n-#define HNS3_RING_GL_RX\t\t0\n-#define HNS3_RING_GL_TX\t\t1\n \n #define HNS3_VECTOR_ELEMENTS_PER_CMD\t10\n \ndiff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c\nindex d4751d478..f6495623e 100644\n--- a/drivers/net/hns3/hns3_ethdev.c\n+++ b/drivers/net/hns3/hns3_ethdev.c\n@@ -2023,34 +2023,98 @@ hns3_check_dcb_cfg(struct rte_eth_dev *dev)\n }\n \n static int\n-hns3_bind_ring_with_vector(struct rte_eth_dev *dev, uint8_t vector_id,\n-\t\t\t   bool mmap, uint16_t queue_id)\n+hns3_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id, bool mmap,\n+\t\t\t   enum hns3_ring_type queue_type, uint16_t queue_id)\n {\n-\tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n \tstruct hns3_cmd_desc desc;\n \tstruct hns3_ctrl_vector_chain_cmd *req =\n \t\t(struct hns3_ctrl_vector_chain_cmd *)desc.data;\n \tenum hns3_cmd_status status;\n \tenum hns3_opcode_type op;\n \tuint16_t tqp_type_and_id = 0;\n+\tconst char *op_str;\n+\tuint16_t type;\n+\tuint16_t gl;\n \n \top = mmap ? HNS3_OPC_ADD_RING_TO_VECTOR : HNS3_OPC_DEL_RING_TO_VECTOR;\n \thns3_cmd_setup_basic_desc(&desc, op, false);\n \treq->int_vector_id = vector_id;\n \n+\tif (queue_type == HNS3_RING_TYPE_RX)\n+\t\tgl = HNS3_RING_GL_RX;\n+\telse\n+\t\tgl = HNS3_RING_GL_TX;\n+\n+\ttype = queue_type;\n+\n \thns3_set_field(tqp_type_and_id, HNS3_INT_TYPE_M, HNS3_INT_TYPE_S,\n-\t\t       HNS3_RING_TYPE_RX);\n+\t\t       type);\n \thns3_set_field(tqp_type_and_id, HNS3_TQP_ID_M, HNS3_TQP_ID_S, queue_id);\n \thns3_set_field(tqp_type_and_id, HNS3_INT_GL_IDX_M, HNS3_INT_GL_IDX_S,\n-\t\t       HNS3_RING_GL_RX);\n+\t\t       gl);\n \treq->tqp_type_and_id[0] = rte_cpu_to_le_16(tqp_type_and_id);\n-\n \treq->int_cause_num = 1;\n+\top_str = mmap ? \"Map\" : \"Unmap\";\n \tstatus = hns3_cmd_send(hw, &desc, 1);\n \tif (status) {\n-\t\thns3_err(hw, \"Map TQP %d fail, vector_id is %d, status is %d.\",\n-\t\t\t queue_id, vector_id, status);\n-\t\treturn -EIO;\n+\t\thns3_err(hw, \"%s TQP %d fail, vector_id is %d, status is %d.\",\n+\t\t\t op_str, queue_id, req->int_vector_id, status);\n+\t\treturn status;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_init_ring_with_vector(struct hns3_hw *hw)\n+{\n+\tuint8_t vec;\n+\tint ret;\n+\tint i;\n+\n+\t/*\n+\t * In hns3 network engine, vector 0 is always the misc interrupt of this\n+\t * function, vector 1~N can be used respectively for the queues of the\n+\t * function. Tx and Rx queues with the same number share the interrupt\n+\t * vector. In the initialization clearing the all hardware mapping\n+\t * relationship configrations between queues and interrupt vectors is\n+\t * needed, so some error caused by the residual configurations, such as\n+\t * the unexpected Tx interrupt, can be avoid. Because of the hardware\n+\t * constraints in hns3 hardware engine, we have to implement clearing\n+\t * the mapping relationship configurations by binding all queues to the\n+\t * last interrupt vector and reserving the last interrupt vector. This\n+\t * method results in a decrease of the maximum queues when upper\n+\t * applications call the rte_eth_dev_configure API function to enable\n+\t * Rx interrupt.\n+\t */\n+\tvec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */\n+\thw->intr_tqps_num = vec - 1; /* the last interrupt is reserved */\n+\tfor (i = 0; i < hw->intr_tqps_num; i++) {\n+\t\t/*\n+\t\t * Set gap limiter and rate limiter configuration of queue's\n+\t\t * interrupt.\n+\t\t */\n+\t\thns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,\n+\t\t\t\t       HNS3_TQP_INTR_GL_DEFAULT);\n+\t\thns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,\n+\t\t\t\t       HNS3_TQP_INTR_GL_DEFAULT);\n+\t\thns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);\n+\n+\t\tret = hns3_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t HNS3_RING_TYPE_TX, i);\n+\t\tif (ret) {\n+\t\t\tPMD_INIT_LOG(ERR, \"PF fail to unbind TX ring(%d) with \"\n+\t\t\t\t\t  \"vector: %d, ret=%d\", i, vec, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tret = hns3_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t HNS3_RING_TYPE_RX, i);\n+\t\tif (ret) {\n+\t\t\tPMD_INIT_LOG(ERR, \"PF fail to unbind RX ring(%d) with \"\n+\t\t\t\t\t  \"vector: %d, ret=%d\", i, vec, ret);\n+\t\t\treturn ret;\n+\t\t}\n \t}\n \n \treturn 0;\n@@ -2227,8 +2291,16 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)\n {\n \tstruct hns3_adapter *hns = eth_dev->data->dev_private;\n \tstruct hns3_hw *hw = &hns->hw;\n+\tuint16_t queue_num = hw->tqps_num;\n \n-\tinfo->max_rx_queues = hw->tqps_num;\n+\t/*\n+\t * In interrupt mode, 'max_rx_queues' is set based on the number of\n+\t * MSI-X interrupt resources of the hardware.\n+\t */\n+\tif (hw->data->dev_conf.intr_conf.rxq == 1)\n+\t\tqueue_num = hw->intr_tqps_num;\n+\n+\tinfo->max_rx_queues = queue_num;\n \tinfo->max_tx_queues = hw->tqps_num;\n \tinfo->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */\n \tinfo->min_rx_bufsize = hw->rx_buf_len;\n@@ -2397,6 +2469,7 @@ hns3_query_pf_resource(struct hns3_hw *hw)\n \tstruct hns3_pf *pf = &hns->pf;\n \tstruct hns3_pf_res_cmd *req;\n \tstruct hns3_cmd_desc desc;\n+\tuint16_t num_msi;\n \tint ret;\n \n \thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_PF_RSRC, true);\n@@ -2428,9 +2501,9 @@ hns3_query_pf_resource(struct hns3_hw *hw)\n \n \tpf->dv_buf_size = roundup(pf->dv_buf_size, HNS3_BUF_SIZE_UNIT);\n \n-\thw->num_msi =\n-\t    hns3_get_field(rte_le_to_cpu_16(req->pf_intr_vector_number),\n-\t\t\t   HNS3_PF_VEC_NUM_M, HNS3_PF_VEC_NUM_S);\n+\tnum_msi = hns3_get_field(rte_le_to_cpu_16(req->pf_intr_vector_number),\n+\t\t\t\t HNS3_VEC_NUM_M, HNS3_VEC_NUM_S);\n+\thw->num_msi = (num_msi > hw->tqps_num + 1) ? hw->tqps_num + 1 : num_msi;\n \n \treturn 0;\n }\n@@ -4025,6 +4098,16 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)\n \t\tgoto err_fdir;\n \t}\n \n+\t/*\n+\t * In the initialization clearing the all hardware mapping relationship\n+\t * configrations between queues and interrupt vectors is needed, so\n+\t * some error caused by the residual configurations, such as the\n+\t * unexpected interrupt, can be avoid.\n+\t */\n+\tret = hns3_init_ring_with_vector(hw);\n+\tif (ret)\n+\t\tgoto err_fdir;\n+\n \treturn 0;\n \n err_fdir:\n@@ -4147,7 +4230,9 @@ hns3_map_rx_interrupt(struct rte_eth_dev *dev)\n \t}\n \tif (rte_intr_dp_is_en(intr_handle)) {\n \t\tfor (q_id = 0; q_id < hw->used_rx_queues; q_id++) {\n-\t\t\tret = hns3_bind_ring_with_vector(dev, vec, true, q_id);\n+\t\t\tret = hns3_bind_ring_with_vector(hw, vec, true,\n+\t\t\t\t\t\t\t HNS3_RING_TYPE_RX,\n+\t\t\t\t\t\t\t q_id);\n \t\t\tif (ret)\n \t\t\t\tgoto bind_vector_error;\n \t\t\tintr_handle->intr_vec[q_id] = vec;\n@@ -4247,7 +4332,9 @@ hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)\n \t}\n \tif (rte_intr_dp_is_en(intr_handle)) {\n \t\tfor (q_id = 0; q_id < hw->used_rx_queues; q_id++) {\n-\t\t\t(void)hns3_bind_ring_with_vector(dev, vec, false, q_id);\n+\t\t\t(void)hns3_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t\t HNS3_RING_TYPE_RX,\n+\t\t\t\t\t\t\t q_id);\n \t\t\tif (vec < base + intr_handle->nb_efd - 1)\n \t\t\t\tvec++;\n \t\t}\ndiff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h\nindex c7625119a..28484188a 100644\n--- a/drivers/net/hns3/hns3_ethdev.h\n+++ b/drivers/net/hns3/hns3_ethdev.h\n@@ -357,6 +357,7 @@ struct hns3_hw {\n \tuint16_t num_msi;\n \tuint16_t total_tqps_num;    /* total task queue pairs of this PF */\n \tuint16_t tqps_num;          /* num task queue pairs of this function */\n+\tuint16_t intr_tqps_num;     /* num queue pairs mapping interrupt */\n \tuint16_t rss_size_max;      /* HW defined max RSS task queue */\n \tuint16_t rx_buf_len;\n \tuint16_t num_tx_desc;       /* desc num of per tx queue */\ndiff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c\nindex 7b776ad13..f4e05e1c5 100644\n--- a/drivers/net/hns3/hns3_ethdev_vf.c\n+++ b/drivers/net/hns3/hns3_ethdev_vf.c\n@@ -429,6 +429,96 @@ hns3vf_set_promisc_mode(struct hns3_hw *hw, bool en_bc_pmc)\n \treturn ret;\n }\n \n+static int\n+hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,\n+\t\t\t     bool mmap, enum hns3_ring_type queue_type,\n+\t\t\t     uint16_t queue_id)\n+{\n+\tstruct hns3_vf_bind_vector_msg bind_msg;\n+\tconst char *op_str;\n+\tuint16_t code;\n+\tint ret;\n+\n+\tmemset(&bind_msg, 0, sizeof(bind_msg));\n+\tcode = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :\n+\t\tHNS3_MBX_UNMAP_RING_TO_VECTOR;\n+\tbind_msg.vector_id = vector_id;\n+\n+\tif (queue_type == HNS3_RING_TYPE_RX)\n+\t\tbind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;\n+\telse\n+\t\tbind_msg.param[0].int_gl_index = HNS3_RING_GL_TX;\n+\n+\tbind_msg.param[0].ring_type = queue_type;\n+\tbind_msg.ring_num = 1;\n+\tbind_msg.param[0].tqp_index = queue_id;\n+\top_str = mmap ? \"Map\" : \"Unmap\";\n+\tret = hns3_send_mbx_msg(hw, code, 0, (uint8_t *)&bind_msg,\n+\t\t\t\tsizeof(bind_msg), false, NULL, 0);\n+\tif (ret) {\n+\t\thns3_err(hw, \"%s TQP %d fail, vector_id is %d, ret is %d.\",\n+\t\t\t op_str, queue_id, bind_msg.vector_id, ret);\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3vf_init_ring_with_vector(struct hns3_hw *hw)\n+{\n+\tuint8_t vec;\n+\tint ret;\n+\tint i;\n+\n+\t/*\n+\t * In hns3 network engine, vector 0 is always the misc interrupt of this\n+\t * function, vector 1~N can be used respectively for the queues of the\n+\t * function. Tx and Rx queues with the same number share the interrupt\n+\t * vector. In the initialization clearing the all hardware mapping\n+\t * relationship configrations between queues and interrupt vectors is\n+\t * needed, so some error caused by the residual configurations, such as\n+\t * the unexpected Tx interrupt, can be avoid. Because of the hardware\n+\t * constraints in hns3 hardware engine, we have to implement clearing\n+\t * the mapping relationship configurations by binding all queues to the\n+\t * last interrupt vector and reserving the last interrupt vector. This\n+\t * method results in a decrease of the maximum queues when upper\n+\t * applications call the rte_eth_dev_configure API function to enable\n+\t * Rx interrupt.\n+\t */\n+\tvec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */\n+\thw->intr_tqps_num = vec - 1; /* the last interrupt is reserved */\n+\tfor (i = 0; i < hw->intr_tqps_num; i++) {\n+\t\t/*\n+\t\t * Set gap limiter and rate limiter configuration of queue's\n+\t\t * interrupt.\n+\t\t */\n+\t\thns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,\n+\t\t\t\t       HNS3_TQP_INTR_GL_DEFAULT);\n+\t\thns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,\n+\t\t\t\t       HNS3_TQP_INTR_GL_DEFAULT);\n+\t\thns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);\n+\n+\t\tret = hns3vf_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t   HNS3_RING_TYPE_TX, i);\n+\t\tif (ret) {\n+\t\t\tPMD_INIT_LOG(ERR, \"VF fail to unbind TX ring(%d) with \"\n+\t\t\t\t\t  \"vector: %d, ret=%d\", i, vec, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tret = hns3vf_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t   HNS3_RING_TYPE_RX, i);\n+\t\tif (ret) {\n+\t\t\tPMD_INIT_LOG(ERR, \"VF fail to unbind RX ring(%d) with \"\n+\t\t\t\t\t  \"vector: %d, ret=%d\", i, vec, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n hns3vf_dev_configure(struct rte_eth_dev *dev)\n {\n@@ -563,8 +653,16 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)\n {\n \tstruct hns3_adapter *hns = eth_dev->data->dev_private;\n \tstruct hns3_hw *hw = &hns->hw;\n+\tuint16_t q_num = hw->tqps_num;\n+\n+\t/*\n+\t * In interrupt mode, 'max_rx_queues' is set based on the number of\n+\t * MSI-X interrupt resources of the hardware.\n+\t */\n+\tif (hw->data->dev_conf.intr_conf.rxq == 1)\n+\t\tq_num = hw->intr_tqps_num;\n \n-\tinfo->max_rx_queues = hw->tqps_num;\n+\tinfo->max_rx_queues = q_num;\n \tinfo->max_tx_queues = hw->tqps_num;\n \tinfo->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */\n \tinfo->min_rx_bufsize = hw->rx_buf_len;\n@@ -1114,6 +1212,35 @@ hns3vf_service_handler(void *param)\n \t\t\t  eth_dev);\n }\n \n+static int\n+hns3_query_vf_resource(struct hns3_hw *hw)\n+{\n+\tstruct hns3_vf_res_cmd *req;\n+\tstruct hns3_cmd_desc desc;\n+\tuint16_t num_msi;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_VF_RSRC, true);\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret) {\n+\t\thns3_err(hw, \"query vf resource failed, ret = %d\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\treq = (struct hns3_vf_res_cmd *)desc.data;\n+\tnum_msi = hns3_get_field(rte_le_to_cpu_16(req->vf_intr_vector_number),\n+\t\t\t\t HNS3_VEC_NUM_M, HNS3_VEC_NUM_S);\n+\tif (num_msi < HNS3_MIN_VECTOR_NUM) {\n+\t\thns3_err(hw, \"Just %u msi resources, not enough for vf(min:%d)\",\n+\t\t\t num_msi, HNS3_MIN_VECTOR_NUM);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\thw->num_msi = (num_msi > hw->tqps_num + 1) ? hw->tqps_num + 1 : num_msi;\n+\n+\treturn 0;\n+}\n+\n static int\n hns3vf_init_hardware(struct hns3_adapter *hns)\n {\n@@ -1190,6 +1317,11 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)\n \t\tgoto err_cmd_init;\n \t}\n \n+\t/* Get VF resource */\n+\tret = hns3_query_vf_resource(hw);\n+\tif (ret)\n+\t\tgoto err_cmd_init;\n+\n \trte_spinlock_init(&hw->mbx_resp.lock);\n \n \thns3vf_clear_event_cause(hw, 0);\n@@ -1239,6 +1371,16 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)\n \n \thns3_set_default_rss_args(hw);\n \n+\t/*\n+\t * In the initialization clearing the all hardware mapping relationship\n+\t * configrations between queues and interrupt vectors is needed, so\n+\t * some error caused by the residual configurations, such as the\n+\t * unexpected interrupt, can be avoid.\n+\t */\n+\tret = hns3vf_init_ring_with_vector(hw);\n+\tif (ret)\n+\t\tgoto err_get_config;\n+\n \treturn 0;\n \n err_get_config:\n@@ -1279,36 +1421,6 @@ hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)\n \thw->io_base = NULL;\n }\n \n-static int\n-hns3vf_bind_ring_with_vector(struct rte_eth_dev *dev, uint8_t vector_id,\n-\t\t\t     bool mmap, uint16_t queue_id)\n-\n-{\n-\tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct hns3_vf_bind_vector_msg bind_msg;\n-\tuint16_t code;\n-\tint ret;\n-\n-\tmemset(&bind_msg, 0, sizeof(bind_msg));\n-\tcode = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :\n-\t\tHNS3_MBX_UNMAP_RING_TO_VECTOR;\n-\tbind_msg.vector_id = vector_id;\n-\tbind_msg.ring_num = 1;\n-\tbind_msg.param[0].ring_type = HNS3_RING_TYPE_RX;\n-\tbind_msg.param[0].tqp_index = queue_id;\n-\tbind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;\n-\n-\tret = hns3_send_mbx_msg(hw, code, 0, (uint8_t *)&bind_msg,\n-\t\t\t\tsizeof(bind_msg), false, NULL, 0);\n-\tif (ret) {\n-\t\thns3_err(hw, \"Map TQP %d fail, vector_id is %d, ret is %d.\",\n-\t\t\t queue_id, vector_id, ret);\n-\t\treturn ret;\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int\n hns3vf_do_stop(struct hns3_adapter *hns)\n {\n@@ -1345,7 +1457,8 @@ hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)\n \t}\n \tif (rte_intr_dp_is_en(intr_handle)) {\n \t\tfor (q_id = 0; q_id < hw->used_rx_queues; q_id++) {\n-\t\t\t(void)hns3vf_bind_ring_with_vector(dev, vec, false,\n+\t\t\t(void)hns3vf_bind_ring_with_vector(hw, vec, false,\n+\t\t\t\t\t\t\t   HNS3_RING_TYPE_RX,\n \t\t\t\t\t\t\t   q_id);\n \t\t\tif (vec < base + intr_handle->nb_efd - 1)\n \t\t\t\tvec++;\n@@ -1511,7 +1624,8 @@ hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)\n \t}\n \tif (rte_intr_dp_is_en(intr_handle)) {\n \t\tfor (q_id = 0; q_id < hw->used_rx_queues; q_id++) {\n-\t\t\tret = hns3vf_bind_ring_with_vector(dev, vec, true,\n+\t\t\tret = hns3vf_bind_ring_with_vector(hw, vec, true,\n+\t\t\t\t\t\t\t   HNS3_RING_TYPE_RX,\n \t\t\t\t\t\t\t   q_id);\n \t\t\tif (ret)\n \t\t\t\tgoto vf_bind_vector_error;\ndiff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h\nindex 42581df67..64bd6931b 100644\n--- a/drivers/net/hns3/hns3_regs.h\n+++ b/drivers/net/hns3/hns3_regs.h\n@@ -83,9 +83,6 @@\n \n #define HNS3_RING_EN_B\t\t\t\t0\n \n-#define HNS3_VECTOR_REG_OFFSET\t\t\t0x4\n-#define HNS3_VECTOR_VF_OFFSET\t\t\t0x100000\n-\n #define HNS3_TQP_REG_OFFSET\t\t\t0x80000\n #define HNS3_TQP_REG_SIZE\t\t\t0x200\n \n@@ -97,6 +94,16 @@\n #define HNS3_TQP_INTR_RL_REG\t\t\t0x20900\n \n #define HNS3_TQP_INTR_REG_SIZE\t\t\t4\n+#define HNS3_TQP_INTR_GL_MAX\t\t\t0x1FE0\n+#define HNS3_TQP_INTR_GL_DEFAULT\t\t20\n+#define HNS3_TQP_INTR_RL_MAX\t\t\t0xEC\n+#define HNS3_TQP_INTR_RL_ENABLE_MASK\t\t0x40\n+#define HNS3_TQP_INTR_RL_DEFAULT\t\t0\n+\n+/* gl_usec convert to hardware count, as writing each 1 represents 2us */\n+#define HNS3_GL_USEC_TO_REG(gl_usec)\t\t((gl_usec) >> 1)\n+/* rl_usec convert to hardware count, as writing each 1 represents 4us */\n+#define HNS3_RL_USEC_TO_REG(rl_usec)\t\t((rl_usec) >> 2)\n \n int hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs);\n #endif /* _HNS3_REGS_H_ */\ndiff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c\nindex aaccf7ef2..ec6d19f58 100644\n--- a/drivers/net/hns3/hns3_rxtx.c\n+++ b/drivers/net/hns3/hns3_rxtx.c\n@@ -499,11 +499,45 @@ hns3_reset_all_queues(struct hns3_adapter *hns)\n }\n \n void\n-hns3_tqp_intr_enable(struct hns3_hw *hw, uint16_t tpq_int_num, bool en)\n+hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,\n+\t\t       uint8_t gl_idx, uint16_t gl_value)\n {\n+\tuint32_t offset[] = {HNS3_TQP_INTR_GL0_REG,\n+\t\t\t     HNS3_TQP_INTR_GL1_REG,\n+\t\t\t     HNS3_TQP_INTR_GL2_REG};\n \tuint32_t addr, value;\n \n-\taddr = HNS3_TQP_INTR_CTRL_REG + tpq_int_num * HNS3_VECTOR_REG_OFFSET;\n+\tif (gl_idx >= RTE_DIM(offset) || gl_value > HNS3_TQP_INTR_GL_MAX)\n+\t\treturn;\n+\n+\taddr = offset[gl_idx] + queue_id * HNS3_TQP_INTR_REG_SIZE;\n+\tvalue = HNS3_GL_USEC_TO_REG(gl_value);\n+\n+\thns3_write_dev(hw, addr, value);\n+}\n+\n+void\n+hns3_set_queue_intr_rl(struct hns3_hw *hw, uint16_t queue_id, uint16_t rl_value)\n+{\n+\tuint32_t addr, value;\n+\n+\tif (rl_value > HNS3_TQP_INTR_RL_MAX)\n+\t\treturn;\n+\n+\taddr = HNS3_TQP_INTR_RL_REG + queue_id * HNS3_TQP_INTR_REG_SIZE;\n+\tvalue = HNS3_RL_USEC_TO_REG(rl_value);\n+\tif (value > 0)\n+\t\tvalue |= HNS3_TQP_INTR_RL_ENABLE_MASK;\n+\n+\thns3_write_dev(hw, addr, value);\n+}\n+\n+static void\n+hns3_queue_intr_enable(struct hns3_hw *hw, uint16_t queue_id, bool en)\n+{\n+\tuint32_t addr, value;\n+\n+\taddr = HNS3_TQP_INTR_CTRL_REG + queue_id * HNS3_TQP_INTR_REG_SIZE;\n \tvalue = en ? 1 : 0;\n \n \thns3_write_dev(hw, addr, value);\n@@ -519,8 +553,7 @@ hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)\n \tif (dev->data->dev_conf.intr_conf.rxq == 0)\n \t\treturn -ENOTSUP;\n \n-\t/* enable the vectors */\n-\thns3_tqp_intr_enable(hw, queue_id, true);\n+\thns3_queue_intr_enable(hw, queue_id, true);\n \n \treturn rte_intr_ack(intr_handle);\n }\n@@ -533,8 +566,7 @@ hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)\n \tif (dev->data->dev_conf.intr_conf.rxq == 0)\n \t\treturn -ENOTSUP;\n \n-\t/* disable the vectors */\n-\thns3_tqp_intr_enable(hw, queue_id, false);\n+\thns3_queue_intr_enable(hw, queue_id, false);\n \n \treturn 0;\n }\n@@ -940,7 +972,6 @@ hns3_fake_rx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)\n \n \tif (hw->fkq_data.rx_queues == NULL && nb_queues != 0) {\n \t\t/* first time configuration */\n-\n \t\tuint32_t size;\n \t\tsize = sizeof(hw->fkq_data.rx_queues[0]) * nb_queues;\n \t\thw->fkq_data.rx_queues = rte_zmalloc(\"fake_rx_queues\", size,\n@@ -951,7 +982,6 @@ hns3_fake_rx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)\n \t\t}\n \t} else if (hw->fkq_data.rx_queues != NULL && nb_queues != 0) {\n \t\t/* re-configure */\n-\n \t\trxq = hw->fkq_data.rx_queues;\n \t\tfor (i = nb_queues; i < old_nb_queues; i++)\n \t\t\thns3_dev_rx_queue_release(rxq[i]);\n@@ -989,7 +1019,6 @@ hns3_fake_tx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)\n \n \tif (hw->fkq_data.tx_queues == NULL && nb_queues != 0) {\n \t\t/* first time configuration */\n-\n \t\tuint32_t size;\n \t\tsize = sizeof(hw->fkq_data.tx_queues[0]) * nb_queues;\n \t\thw->fkq_data.tx_queues = rte_zmalloc(\"fake_tx_queues\", size,\n@@ -1000,7 +1029,6 @@ hns3_fake_tx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)\n \t\t}\n \t} else if (hw->fkq_data.tx_queues != NULL && nb_queues != 0) {\n \t\t/* re-configure */\n-\n \t\ttxq = hw->fkq_data.tx_queues;\n \t\tfor (i = nb_queues; i < old_nb_queues; i++)\n \t\t\thns3_dev_tx_queue_release(txq[i]);\ndiff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h\nindex 1c2723ffb..5ba6ee915 100644\n--- a/drivers/net/hns3/hns3_rxtx.h\n+++ b/drivers/net/hns3/hns3_rxtx.h\n@@ -320,7 +320,10 @@ uint16_t hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,\n \t\t\tuint16_t nb_pkts);\n const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev);\n void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev);\n-void hns3_tqp_intr_enable(struct hns3_hw *hw, uint16_t tpq_int_num, bool en);\n+void hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,\n+\t\t\t    uint8_t gl_idx, uint16_t gl_value);\n+void hns3_set_queue_intr_rl(struct hns3_hw *hw, uint16_t queue_id,\n+\t\t\t    uint16_t rl_value);\n int hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,\n \t\t\t\t  uint16_t nb_tx_q);\n \n",
    "prefixes": [
        "v2",
        "2/5"
    ]
}