From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 850C9A0526; Mon, 20 Jan 2020 18:08:24 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id ED1941C0BD; Mon, 20 Jan 2020 18:04:05 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id C23A41BFAF for ; Mon, 20 Jan 2020 18:03:14 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from asafp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 20 Jan 2020 19:03:13 +0200 Received: from pegasus07.mtr.labs.mlnx (pegasus07.mtr.labs.mlnx [10.210.16.112]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 00KH3BGn024424; Mon, 20 Jan 2020 19:03:13 +0200 From: Matan Azrad To: dev@dpdk.org Cc: Maxime Coquelin , Thomas Monjalon Date: Mon, 20 Jan 2020 17:03:02 +0000 Message-Id: <1579539790-3882-31-git-send-email-matan@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1579539790-3882-1-git-send-email-matan@mellanox.com> References: <1579539790-3882-1-git-send-email-matan@mellanox.com> Subject: [dpdk-dev] [PATCH v1 30/38] vdpa/mlx5: map doorbell X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The HW support only 4 bytes doorbell writing detection. The virtio device set only 2 bytes when it rings the doorbell. Map the virtio doorbell detected by the virtio queue kickfd to the HW VAR space when it expects to get the virtio emulation doorbell. Use the EAL interrupt mechanism to get notification when a new event appears in kickfd by the guest and write 4 bytes to the HW doorbell space in the notification callback. Signed-off-by: Matan Azrad --- drivers/vdpa/mlx5/mlx5_vdpa.h | 3 ++ drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 84 ++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h index 318f1e8..8503b7b 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/mlx5_vdpa.h @@ -66,6 +66,7 @@ struct mlx5_vdpa_virtq { void *buf; uint32_t size; } umems[3]; + struct rte_intr_handle intr_handle; }; struct mlx5_vdpa_steer { @@ -103,6 +104,8 @@ struct mlx5_vdpa_priv { uint16_t log_max_rqt_size; SLIST_HEAD(virtq_list, mlx5_vdpa_virtq) virtq_list; struct mlx5_vdpa_steer steer; + struct mlx5dv_var *var; + void *virtq_db_addr; SLIST_HEAD(mr_list, mlx5_vdpa_query_mr) mr_list; }; diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c index a294117..fbcf971 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c @@ -3,20 +3,65 @@ */ #include #include +#include +#include #include #include +#include #include "mlx5_vdpa_utils.h" #include "mlx5_vdpa.h" +static void +mlx5_vdpa_virtq_handler(void *cb_arg) +{ + struct mlx5_vdpa_virtq *virtq = cb_arg; + struct mlx5_vdpa_priv *priv = virtq->priv; + uint64_t buf; + int nbytes; + + do { + nbytes = read(virtq->intr_handle.fd, &buf, 8); + if (nbytes < 0) { + if (errno == EINTR || + errno == EWOULDBLOCK || + errno == EAGAIN) + continue; + DRV_LOG(ERR, "Failed to read kickfd of virtq %d: %s", + virtq->index, strerror(errno)); + } + break; + } while (1); + assert(priv->virtq_db_addr); + rte_write32(virtq->index, priv->virtq_db_addr); + DRV_LOG(DEBUG, "Ring virtq %u doorbell.", virtq->index); +} + static int mlx5_vdpa_virtq_unset(struct mlx5_vdpa_virtq *virtq) { - int ret __rte_unused; unsigned i; + int retries = MLX5_VDPA_INTR_RETRIES; + int ret = -EAGAIN; + if (virtq->intr_handle.fd) { + while (retries-- && ret == -EAGAIN) { + ret = rte_intr_callback_unregister(&virtq->intr_handle, + mlx5_vdpa_virtq_handler, + virtq); + if (ret == -EAGAIN) { + DRV_LOG(DEBUG, "Try again to unregister fd %d " + "of virtq %d interrupt, retries = %d.", + virtq->intr_handle.fd, + (int)virtq->index, retries); + usleep(MLX5_VDPA_INTR_RETRIES_USEC); + } + } + assert(!ret); + memset(&virtq->intr_handle, 0, sizeof(virtq->intr_handle)); + } if (virtq->virtq) { ret = mlx5_devx_cmd_destroy(virtq->virtq); assert(!ret); @@ -62,6 +107,15 @@ assert(!ret); priv->td = NULL; } + if (priv->virtq_db_addr) { + ret = munmap(priv->virtq_db_addr, priv->var->length); + assert(!ret); + priv->virtq_db_addr = NULL; + } + if (priv->var) { + mlx5_glue->dv_free_var(priv->var); + priv->var = NULL; + } priv->features = 0; } @@ -207,6 +261,17 @@ if (mlx5_vdpa_virtq_modify(virtq, 1)) goto error; virtq->enable = 1; + virtq->intr_handle.fd = vq.kickfd; + virtq->intr_handle.type = RTE_INTR_HANDLE_EXT; + if (rte_intr_callback_register(&virtq->intr_handle, + mlx5_vdpa_virtq_handler, virtq)) { + virtq->intr_handle.fd = 0; + DRV_LOG(ERR, "Failed to register virtq %d interrupt.", index); + goto error; + } else { + DRV_LOG(DEBUG, "Register fd %d interrupt for virtq %d.", + virtq->intr_handle.fd, index); + } return 0; error: mlx5_vdpa_virtq_unset(virtq); @@ -281,6 +346,23 @@ DRV_LOG(ERR, "Failed to configure negotiated features."); return -1; } + priv->var = mlx5_glue->dv_alloc_var(priv->ctx, 0); + if (!priv->var) { + DRV_LOG(ERR, "Failed to allocate VAR %u.\n", errno); + return -1; + } + /* Always map the entire page. */ + priv->virtq_db_addr = mmap(NULL, priv->var->length, PROT_READ | + PROT_WRITE, MAP_SHARED, priv->ctx->cmd_fd, + priv->var->mmap_off); + if (priv->virtq_db_addr == MAP_FAILED) { + DRV_LOG(ERR, "Failed to map doorbell page %u.", errno); + priv->virtq_db_addr = NULL; + goto error; + } else { + DRV_LOG(DEBUG, "VAR address of doorbell mapping is %p.", + priv->virtq_db_addr); + } priv->td = mlx5_devx_cmd_create_td(priv->ctx); if (!priv->td) { DRV_LOG(ERR, "Failed to create transpprt domain."); -- 1.8.3.1