get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 82167,
    "url": "https://patches.dpdk.org/api/patches/82167/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1603696570-8606-2-git-send-email-xuemingl@nvidia.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": "<1603696570-8606-2-git-send-email-xuemingl@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1603696570-8606-2-git-send-email-xuemingl@nvidia.com",
    "date": "2020-10-26T07:16:10",
    "name": "[2/2] vdpa/mlx5: hardware error handling",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "47090bc70a904d8ae63067f99ee54c73db0b0794",
    "submitter": {
        "id": 1904,
        "url": "https://patches.dpdk.org/api/people/1904/?format=api",
        "name": "Xueming Li",
        "email": "xuemingl@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "https://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1603696570-8606-2-git-send-email-xuemingl@nvidia.com/mbox/",
    "series": [
        {
            "id": 13314,
            "url": "https://patches.dpdk.org/api/series/13314/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=13314",
            "date": "2020-10-26T07:16:09",
            "name": "[1/2] common/mlx5: add virtq attributes error fields",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/13314/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/82167/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/82167/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 363C4A04B5;\n\tMon, 26 Oct 2020 08:16:51 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id EF0772BB8;\n\tMon, 26 Oct 2020 08:16:43 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 4560C1D9E\n for <dev@dpdk.org>; Mon, 26 Oct 2020 08:16:42 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n xuemingl@nvidia.com) with SMTP; 26 Oct 2020 09:16:37 +0200",
            "from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 09Q7GQG0005675;\n Mon, 26 Oct 2020 09:16:37 +0200"
        ],
        "From": "Xueming Li <xuemingl@nvidia.com>",
        "To": "Matan Azrad <matan@nvidia.com>,\n Viacheslav Ovsiienko <viacheslavo@nvidia.com>",
        "Cc": "dev@dpdk.org, xuemingl@nvidia.com, Asaf Penso <asafp@nvidia.com>",
        "Date": "Mon, 26 Oct 2020 07:16:10 +0000",
        "Message-Id": "<1603696570-8606-2-git-send-email-xuemingl@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1603696570-8606-1-git-send-email-xuemingl@nvidia.com>",
        "References": "<1603696570-8606-1-git-send-email-xuemingl@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH 2/2] vdpa/mlx5: hardware error handling",
        "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": "When hardware error happens, vdpa didn't get such information and leave\ndriver in silent: working state but no response.\n\nThis patch subscribes firmware virtq error event and try to recover max\n3 times in 10 seconds, stop virtq if max retry number reached.\n\nWhen error happens, PMD log in warning level. If failed to recover,\noutputs error log. Query virtq statitics to get error counters report.\n\nAcked-by: Matan Azrad <matan@nvidia.com>\nSigned-off-by: Xueming Li <xuemingl@nvidia.com>\n---\n drivers/vdpa/mlx5/mlx5_vdpa.c       |   2 +\n drivers/vdpa/mlx5/mlx5_vdpa.h       |  37 ++++++++\n drivers/vdpa/mlx5/mlx5_vdpa_event.c | 140 ++++++++++++++++++++++++++++\n drivers/vdpa/mlx5/mlx5_vdpa_virtq.c |  61 +++++++++---\n 4 files changed, 225 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c\nindex a8f3e4b1de..ba779c10ee 100644\n--- a/drivers/vdpa/mlx5/mlx5_vdpa.c\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c\n@@ -283,6 +283,7 @@ mlx5_vdpa_dev_close(int vid)\n \t}\n \tif (priv->configured)\n \t\tret |= mlx5_vdpa_lm_log(priv);\n+\tmlx5_vdpa_err_event_unset(priv);\n \tmlx5_vdpa_cqe_event_unset(priv);\n \tmlx5_vdpa_steer_unset(priv);\n \tmlx5_vdpa_virtqs_release(priv);\n@@ -318,6 +319,7 @@ mlx5_vdpa_dev_config(int vid)\n \t\tDRV_LOG(WARNING, \"MTU cannot be set on device %s.\",\n \t\t\t\tvdev->device->name);\n \tif (mlx5_vdpa_pd_create(priv) || mlx5_vdpa_mem_register(priv) ||\n+\t    mlx5_vdpa_err_event_setup(priv) ||\n \t    mlx5_vdpa_virtqs_prepare(priv) || mlx5_vdpa_steer_setup(priv) ||\n \t    mlx5_vdpa_cqe_event_setup(priv)) {\n \t\tmlx5_vdpa_dev_close(vid);\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h\nindex fcbc12ab0c..0d6886c52c 100644\n--- a/drivers/vdpa/mlx5/mlx5_vdpa.h\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h\n@@ -87,6 +87,7 @@ struct mlx5_vdpa_virtq {\n \tuint16_t vq_size;\n \tuint8_t notifier_state;\n \tbool stopped;\n+\tuint32_t version;\n \tstruct mlx5_vdpa_priv *priv;\n \tstruct mlx5_devx_obj *virtq;\n \tstruct mlx5_devx_obj *counters;\n@@ -97,6 +98,8 @@ struct mlx5_vdpa_virtq {\n \t\tuint32_t size;\n \t} umems[3];\n \tstruct rte_intr_handle intr_handle;\n+\tuint64_t err_time[3]; /* RDTSC time of recent errors. */\n+\tuint32_t n_retry;\n \tstruct mlx5_devx_virtio_q_couners_attr reset;\n };\n \n@@ -143,8 +146,10 @@ struct mlx5_vdpa_priv {\n \tstruct rte_vhost_memory *vmem;\n \tuint32_t eqn;\n \tstruct mlx5dv_devx_event_channel *eventc;\n+\tstruct mlx5dv_devx_event_channel *err_chnl;\n \tstruct mlx5dv_devx_uar *uar;\n \tstruct rte_intr_handle intr_handle;\n+\tstruct rte_intr_handle err_intr_handle;\n \tstruct mlx5_devx_obj *td;\n \tstruct mlx5_devx_obj *tis;\n \tuint16_t nr_virtqs;\n@@ -259,6 +264,25 @@ int mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv);\n  */\n void mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv);\n \n+/**\n+ * Setup error interrupt handler.\n+ *\n+ * @param[in] priv\n+ *   The vdpa driver private structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int mlx5_vdpa_err_event_setup(struct mlx5_vdpa_priv *priv);\n+\n+/**\n+ * Unset error event handler.\n+ *\n+ * @param[in] priv\n+ *   The vdpa driver private structure.\n+ */\n+void mlx5_vdpa_err_event_unset(struct mlx5_vdpa_priv *priv);\n+\n /**\n  * Release a virtq and all its related resources.\n  *\n@@ -392,6 +416,19 @@ int mlx5_vdpa_virtq_modify(struct mlx5_vdpa_virtq *virtq, int state);\n  */\n int mlx5_vdpa_virtq_stop(struct mlx5_vdpa_priv *priv, int index);\n \n+/**\n+ * Query virtq information.\n+ *\n+ * @param[in] priv\n+ *   The vdpa driver private structure.\n+ * @param[in] index\n+ *   The virtq index.\n+ *\n+ * @return\n+ *   0 on success, a negative value otherwise.\n+ */\n+int mlx5_vdpa_virtq_query(struct mlx5_vdpa_priv *priv, int index);\n+\n /**\n  * Get virtq statistics.\n  *\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c\nindex 8a01e42794..89df699dad 100644\n--- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c\n@@ -15,11 +15,14 @@\n #include <rte_alarm.h>\n \n #include <mlx5_common.h>\n+#include <mlx5_glue.h>\n \n #include \"mlx5_vdpa_utils.h\"\n #include \"mlx5_vdpa.h\"\n \n \n+#define MLX5_VDPA_ERROR_TIME_SEC 3u\n+\n void\n mlx5_vdpa_event_qp_global_release(struct mlx5_vdpa_priv *priv)\n {\n@@ -378,6 +381,143 @@ mlx5_vdpa_interrupt_handler(void *cb_arg)\n \tpthread_mutex_unlock(&priv->vq_config_lock);\n }\n \n+static void\n+mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused)\n+{\n+#ifdef HAVE_IBV_DEVX_EVENT\n+\tstruct mlx5_vdpa_priv *priv = cb_arg;\n+\tunion {\n+\t\tstruct mlx5dv_devx_async_event_hdr event_resp;\n+\t\tuint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];\n+\t} out;\n+\tuint32_t vq_index, i, version;\n+\tstruct mlx5_vdpa_virtq *virtq;\n+\tuint64_t sec;\n+\n+\tpthread_mutex_lock(&priv->vq_config_lock);\n+\twhile (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp,\n+\t\t\t\t\t sizeof(out.buf)) >=\n+\t\t\t\t       (ssize_t)sizeof(out.event_resp.cookie)) {\n+\t\tvq_index = out.event_resp.cookie && UINT32_MAX;\n+\t\tversion = out.event_resp.cookie >> 32;\n+\t\tif (vq_index >= priv->nr_virtqs) {\n+\t\t\tDRV_LOG(ERR, \"Invalid device %s error event virtq %d.\",\n+\t\t\t\tpriv->vdev->device->name, vq_index);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tvirtq = &priv->virtqs[vq_index];\n+\t\tif (!virtq->enable || virtq->version != version)\n+\t\t\tcontinue;\n+\t\tif (rte_rdtsc() / rte_get_tsc_hz() < MLX5_VDPA_ERROR_TIME_SEC)\n+\t\t\tcontinue;\n+\t\tvirtq->stopped = true;\n+\t\t/* Query error info. */\n+\t\tif (mlx5_vdpa_virtq_query(priv, vq_index))\n+\t\t\tgoto log;\n+\t\t/* Disable vq. */\n+\t\tif (mlx5_vdpa_virtq_enable(priv, vq_index, 0)) {\n+\t\t\tDRV_LOG(ERR, \"Failed to disable virtq %d.\", vq_index);\n+\t\t\tgoto log;\n+\t\t}\n+\t\t/* Retry if error happens less than N times in 3 seconds. */\n+\t\tsec = (rte_rdtsc() - virtq->err_time[0]) / rte_get_tsc_hz();\n+\t\tif (sec > MLX5_VDPA_ERROR_TIME_SEC) {\n+\t\t\t/* Retry. */\n+\t\t\tif (mlx5_vdpa_virtq_enable(priv, vq_index, 1))\n+\t\t\t\tDRV_LOG(ERR, \"Failed to enable virtq %d.\",\n+\t\t\t\t\tvq_index);\n+\t\t\telse\n+\t\t\t\tDRV_LOG(WARNING, \"Recover virtq %d: %u.\",\n+\t\t\t\t\tvq_index, ++virtq->n_retry);\n+\t\t} else {\n+\t\t\t/* Retry timeout, give up. */\n+\t\t\tDRV_LOG(ERR, \"Device %s virtq %d failed to recover.\",\n+\t\t\t\tpriv->vdev->device->name, vq_index);\n+\t\t}\n+log:\n+\t\t/* Shift in current time to error time log end. */\n+\t\tfor (i = 1; i < RTE_DIM(virtq->err_time); i++)\n+\t\t\tvirtq->err_time[i - 1] = virtq->err_time[i];\n+\t\tvirtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc();\n+\t}\n+\tpthread_mutex_unlock(&priv->vq_config_lock);\n+#endif\n+}\n+\n+int\n+mlx5_vdpa_err_event_setup(struct mlx5_vdpa_priv *priv)\n+{\n+\tint ret;\n+\tint flags;\n+\n+\t/* Setup device event channel. */\n+\tpriv->err_chnl = mlx5_glue->devx_create_event_channel(priv->ctx, 0);\n+\tif (!priv->err_chnl) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR, \"Failed to create device event channel %d.\",\n+\t\t\trte_errno);\n+\t\tgoto error;\n+\t}\n+\tflags = fcntl(priv->err_chnl->fd, F_GETFL);\n+\tret = fcntl(priv->err_chnl->fd, F_SETFL, flags | O_NONBLOCK);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"Failed to change device event channel FD.\");\n+\t\tgoto error;\n+\t}\n+\tpriv->err_intr_handle.fd = priv->err_chnl->fd;\n+\tpriv->err_intr_handle.type = RTE_INTR_HANDLE_EXT;\n+\tif (rte_intr_callback_register(&priv->err_intr_handle,\n+\t\t\t\t       mlx5_vdpa_err_interrupt_handler,\n+\t\t\t\t       priv)) {\n+\t\tpriv->err_intr_handle.fd = 0;\n+\t\tDRV_LOG(ERR, \"Failed to register error interrupt for device %d.\",\n+\t\t\tpriv->vid);\n+\t\tgoto error;\n+\t} else {\n+\t\tDRV_LOG(DEBUG, \"Registered error interrupt for device%d.\",\n+\t\t\tpriv->vid);\n+\t}\n+\treturn 0;\n+error:\n+\tmlx5_vdpa_err_event_unset(priv);\n+\treturn -1;\n+}\n+\n+void\n+mlx5_vdpa_err_event_unset(struct mlx5_vdpa_priv *priv)\n+{\n+\tint retries = MLX5_VDPA_INTR_RETRIES;\n+\tint ret = -EAGAIN;\n+\tunion {\n+\t\tstruct mlx5dv_devx_async_event_hdr event_resp;\n+\t\tuint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128];\n+\t} out;\n+\n+\tif (!priv->err_intr_handle.fd)\n+\t\treturn;\n+\twhile (retries-- && ret == -EAGAIN) {\n+\t\tret = rte_intr_callback_unregister(&priv->err_intr_handle,\n+\t\t\t\t\t    mlx5_vdpa_err_interrupt_handler,\n+\t\t\t\t\t    priv);\n+\t\tif (ret == -EAGAIN) {\n+\t\t\tDRV_LOG(DEBUG, \"Try again to unregister fd %d \"\n+\t\t\t\t\"of error interrupt, retries = %d.\",\n+\t\t\t\tpriv->err_intr_handle.fd, retries);\n+\t\t\trte_pause();\n+\t\t}\n+\t}\n+\tmemset(&priv->err_intr_handle, 0, sizeof(priv->err_intr_handle));\n+\tif (priv->err_chnl) {\n+\t\t/* Clean all pending events. */\n+\t\twhile (mlx5_glue->devx_get_event(priv->err_chnl,\n+\t\t       &out.event_resp, sizeof(out.buf)) >=\n+\t\t       (ssize_t)sizeof(out.event_resp.cookie))\n+\t\t\t;\n+\t\tmlx5_glue->devx_destroy_event_channel(priv->err_chnl);\n+\t\tpriv->err_chnl = NULL;\n+\t}\n+}\n+\n int\n mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv)\n {\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c\nindex 17e71cf4f4..d5ac040544 100644\n--- a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c\n@@ -88,11 +88,6 @@ mlx5_vdpa_virtq_unset(struct mlx5_vdpa_virtq *virtq)\n \t\t\trte_free(virtq->umems[i].buf);\n \t}\n \tmemset(&virtq->umems, 0, sizeof(virtq->umems));\n-\tif (virtq->counters) {\n-\t\tclaim_zero(mlx5_devx_cmd_destroy(virtq->counters));\n-\t\tvirtq->counters = NULL;\n-\t}\n-\tmemset(&virtq->reset, 0, sizeof(virtq->reset));\n \tif (virtq->eqp.fw_qp)\n \t\tmlx5_vdpa_event_qp_destroy(&virtq->eqp);\n \tvirtq->notifier_state = MLX5_VDPA_NOTIFIER_STATE_DISABLED;\n@@ -103,9 +98,19 @@ void\n mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv)\n {\n \tint i;\n+\tstruct mlx5_vdpa_virtq *virtq;\n \n-\tfor (i = 0; i < priv->nr_virtqs; i++)\n-\t\tmlx5_vdpa_virtq_unset(&priv->virtqs[i]);\n+\tfor (i = 0; i < priv->nr_virtqs; i++) {\n+\t\tvirtq = &priv->virtqs[i];\n+\t\tmlx5_vdpa_virtq_unset(virtq);\n+\t\tif (virtq->counters) {\n+\t\t\tclaim_zero(mlx5_devx_cmd_destroy(virtq->counters));\n+\t\t\tvirtq->counters = NULL;\n+\t\t\tmemset(&virtq->reset, 0, sizeof(virtq->reset));\n+\t\t}\n+\t\tmemset(virtq->err_time, 0, sizeof(virtq->err_time));\n+\t\tvirtq->n_retry = 0;\n+\t}\n \tif (priv->tis) {\n \t\tclaim_zero(mlx5_devx_cmd_destroy(priv->tis));\n \t\tpriv->tis = NULL;\n@@ -138,7 +143,6 @@ mlx5_vdpa_virtq_modify(struct mlx5_vdpa_virtq *virtq, int state)\n int\n mlx5_vdpa_virtq_stop(struct mlx5_vdpa_priv *priv, int index)\n {\n-\tstruct mlx5_devx_virtq_attr attr = {0};\n \tstruct mlx5_vdpa_virtq *virtq = &priv->virtqs[index];\n \tint ret;\n \n@@ -148,6 +152,17 @@ mlx5_vdpa_virtq_stop(struct mlx5_vdpa_priv *priv, int index)\n \tif (ret)\n \t\treturn -1;\n \tvirtq->stopped = true;\n+\tDRV_LOG(DEBUG, \"vid %u virtq %u was stopped.\", priv->vid, index);\n+\treturn mlx5_vdpa_virtq_query(priv, index);\n+}\n+\n+int\n+mlx5_vdpa_virtq_query(struct mlx5_vdpa_priv *priv, int index)\n+{\n+\tstruct mlx5_devx_virtq_attr attr = {0};\n+\tstruct mlx5_vdpa_virtq *virtq = &priv->virtqs[index];\n+\tint ret;\n+\n \tif (mlx5_devx_cmd_query_virtq(virtq->virtq, &attr)) {\n \t\tDRV_LOG(ERR, \"Failed to query virtq %d.\", index);\n \t\treturn -1;\n@@ -162,7 +177,9 @@ mlx5_vdpa_virtq_stop(struct mlx5_vdpa_priv *priv, int index)\n \t\tDRV_LOG(ERR, \"Failed to set virtq %d base.\", index);\n \t\treturn -1;\n \t}\n-\tDRV_LOG(DEBUG, \"vid %u virtq %u was stopped.\", priv->vid, index);\n+\tif (attr.state == MLX5_VIRTQ_STATE_ERROR)\n+\t\tDRV_LOG(WARNING, \"vid %d vring %d hw error=%hhu\",\n+\t\t\tpriv->vid, index, attr.error_type);\n \treturn 0;\n }\n \n@@ -195,6 +212,8 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)\n \tunsigned int i;\n \tuint16_t last_avail_idx;\n \tuint16_t last_used_idx;\n+\tuint16_t event_num = MLX5_EVENT_TYPE_OBJECT_CHANGE;\n+\tuint64_t cookie;\n \n \tret = rte_vhost_get_vhost_vring(priv->vid, index, &vq);\n \tif (ret)\n@@ -231,8 +250,9 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)\n \t\t\t\" need event QPs and event mechanism.\", index);\n \t}\n \tif (priv->caps.queue_counters_valid) {\n-\t\tvirtq->counters = mlx5_devx_cmd_create_virtio_q_counters\n-\t\t\t\t\t\t\t\t    (priv->ctx);\n+\t\tif (!virtq->counters)\n+\t\t\tvirtq->counters = mlx5_devx_cmd_create_virtio_q_counters\n+\t\t\t\t\t\t\t\t(priv->ctx);\n \t\tif (!virtq->counters) {\n \t\t\tDRV_LOG(ERR, \"Failed to create virtq couners for virtq\"\n \t\t\t\t\" %d.\", index);\n@@ -332,6 +352,19 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)\n \t\t\t\tvirtq->intr_handle.fd, index);\n \t\t}\n \t}\n+\t/* Subscribe virtq error event. */\n+\tvirtq->version++;\n+\tcookie = ((uint64_t)virtq->version << 32) + index;\n+\tret = mlx5_glue->devx_subscribe_devx_event(priv->err_chnl,\n+\t\t\t\t\t\t   virtq->virtq->obj,\n+\t\t\t\t\t\t   sizeof(event_num),\n+\t\t\t\t\t\t   &event_num, cookie);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"Failed to subscribe device %d virtq %d error event.\",\n+\t\t\tpriv->vid, index);\n+\t\trte_errno = errno;\n+\t\tgoto error;\n+\t}\n \tvirtq->stopped = false;\n \tDRV_LOG(DEBUG, \"vid %u virtq %u was created successfully.\", priv->vid,\n \t\tindex);\n@@ -526,12 +559,11 @@ mlx5_vdpa_virtq_stats_get(struct mlx5_vdpa_priv *priv, int qid,\n \tstruct mlx5_devx_virtio_q_couners_attr attr = {0};\n \tint ret;\n \n-\tif (!virtq->virtq || !virtq->enable) {\n+\tif (!virtq->counters) {\n \t\tDRV_LOG(ERR, \"Failed to read virtq %d statistics - virtq \"\n \t\t\t\"is invalid.\", qid);\n \t\treturn -EINVAL;\n \t}\n-\tMLX5_ASSERT(virtq->counters);\n \tret = mlx5_devx_cmd_query_virtio_q_counters(virtq->counters, &attr);\n \tif (ret) {\n \t\tDRV_LOG(ERR, \"Failed to read virtq %d stats from HW.\", qid);\n@@ -583,12 +615,11 @@ mlx5_vdpa_virtq_stats_reset(struct mlx5_vdpa_priv *priv, int qid)\n \tstruct mlx5_vdpa_virtq *virtq = &priv->virtqs[qid];\n \tint ret;\n \n-\tif (!virtq->virtq || !virtq->enable) {\n+\tif (!virtq->counters) {\n \t\tDRV_LOG(ERR, \"Failed to read virtq %d statistics - virtq \"\n \t\t\t\"is invalid.\", qid);\n \t\treturn -EINVAL;\n \t}\n-\tMLX5_ASSERT(virtq->counters);\n \tret = mlx5_devx_cmd_query_virtio_q_counters(virtq->counters,\n \t\t\t\t\t\t    &virtq->reset);\n \tif (ret)\n",
    "prefixes": [
        "2/2"
    ]
}