get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 65292,
    "url": "http://patches.dpdk.org/api/patches/65292/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1580292549-27439-5-git-send-email-matan@mellanox.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": "<1580292549-27439-5-git-send-email-matan@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1580292549-27439-5-git-send-email-matan@mellanox.com",
    "date": "2020-01-29T10:09:00",
    "name": "[v2,04/13] vdpa/mlx5: prepare memory regions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8705a368a6503dab32427c1cff58eefe58f34002",
    "submitter": {
        "id": 796,
        "url": "http://patches.dpdk.org/api/people/796/?format=api",
        "name": "Matan Azrad",
        "email": "matan@mellanox.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1580292549-27439-5-git-send-email-matan@mellanox.com/mbox/",
    "series": [
        {
            "id": 8335,
            "url": "http://patches.dpdk.org/api/series/8335/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8335",
            "date": "2020-01-29T10:08:56",
            "name": "Introduce mlx5 vDPA driver",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/8335/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/65292/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/65292/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 3EFC2A0531;\n\tWed, 29 Jan 2020 11:09:58 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 696601BFDB;\n\tWed, 29 Jan 2020 11:09:46 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 6E8211BFDB\n for <dev@dpdk.org>; Wed, 29 Jan 2020 11:09:44 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n asafp@mellanox.com)\n with ESMTPS (AES256-SHA encrypted); 29 Jan 2020 12:09:39 +0200",
            "from pegasus07.mtr.labs.mlnx (pegasus07.mtr.labs.mlnx\n [10.210.16.112])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 00TA9BHK032108;\n Wed, 29 Jan 2020 12:09:39 +0200"
        ],
        "From": "Matan Azrad <matan@mellanox.com>",
        "To": "dev@dpdk.org, Viacheslav Ovsiienko <viacheslavo@mellanox.com>",
        "Cc": "Maxime Coquelin <maxime.coquelin@redhat.com>",
        "Date": "Wed, 29 Jan 2020 10:09:00 +0000",
        "Message-Id": "<1580292549-27439-5-git-send-email-matan@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1580292549-27439-1-git-send-email-matan@mellanox.com>",
        "References": "<1579539790-3882-1-git-send-email-matan@mellanox.com>\n <1580292549-27439-1-git-send-email-matan@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v2 04/13] vdpa/mlx5: prepare memory regions",
        "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": "In order to map the guest physical addresses used by the virtio device\nguest side to the host physical addresses used by the HW as the host\nside, memory regions are created.\n\nBy this way, for example, the HW can translate the addresses of the\npackets posted by the guest and to take the packets from the correct\nplace.\n\nThe design is to work with single MR which will be configured to the\nvirtio queues in the HW, hence a lot of direct MRs are grouped to single\nindirect MR.\n\nCreate functions to prepare and release MRs with all the related\nresources that are required for it.\n\nCreate a new file mlx5_vdpa_mem.c to manage all the MR related code\nin the driver.\n\nSigned-off-by: Matan Azrad <matan@mellanox.com>\nAcked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>\n---\n drivers/vdpa/mlx5/Makefile        |   4 +-\n drivers/vdpa/mlx5/meson.build     |   3 +-\n drivers/vdpa/mlx5/mlx5_vdpa.c     |  11 +-\n drivers/vdpa/mlx5/mlx5_vdpa.h     |  60 +++++++\n drivers/vdpa/mlx5/mlx5_vdpa_mem.c | 346 ++++++++++++++++++++++++++++++++++++++\n 5 files changed, 413 insertions(+), 11 deletions(-)\n create mode 100644 drivers/vdpa/mlx5/mlx5_vdpa.h\n create mode 100644 drivers/vdpa/mlx5/mlx5_vdpa_mem.c",
    "diff": "diff --git a/drivers/vdpa/mlx5/Makefile b/drivers/vdpa/mlx5/Makefile\nindex c1c8cc0..5472797 100644\n--- a/drivers/vdpa/mlx5/Makefile\n+++ b/drivers/vdpa/mlx5/Makefile\n@@ -8,6 +8,7 @@ LIB = librte_pmd_mlx5_vdpa.a\n \n # Sources.\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_VDPA_PMD) += mlx5_vdpa.c\n+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_VDPA_PMD) += mlx5_vdpa_mem.c\n \n # Basic CFLAGS.\n CFLAGS += -O3\n@@ -15,6 +16,7 @@ CFLAGS += -std=c11 -Wall -Wextra\n CFLAGS += -g\n CFLAGS += -I$(RTE_SDK)/drivers/common/mlx5\n CFLAGS += -I$(RTE_SDK)/drivers/net/mlx5_vdpa\n+CFLAGS += -I$(RTE_SDK)/lib/librte_sched\n CFLAGS += -I$(BUILDDIR)/drivers/common/mlx5\n CFLAGS += -D_BSD_SOURCE\n CFLAGS += -D_DEFAULT_SOURCE\n@@ -22,7 +24,7 @@ CFLAGS += -D_XOPEN_SOURCE=600\n CFLAGS += $(WERROR_FLAGS)\n CFLAGS += -Wno-strict-prototypes\n LDLIBS += -lrte_common_mlx5\n-LDLIBS += -lrte_eal -lrte_vhost -lrte_kvargs -lrte_bus_pci\n+LDLIBS += -lrte_eal -lrte_vhost -lrte_kvargs -lrte_bus_pci -lrte_sched\n \n # A few warnings cannot be avoided in external headers.\n CFLAGS += -Wno-error=cast-qual\ndiff --git a/drivers/vdpa/mlx5/meson.build b/drivers/vdpa/mlx5/meson.build\nindex 4bca6ea..7e5dd95 100644\n--- a/drivers/vdpa/mlx5/meson.build\n+++ b/drivers/vdpa/mlx5/meson.build\n@@ -9,9 +9,10 @@ endif\n \n fmt_name = 'mlx5_vdpa'\n allow_experimental_apis = true\n-deps += ['hash', 'common_mlx5', 'vhost', 'bus_pci', 'eal']\n+deps += ['hash', 'common_mlx5', 'vhost', 'bus_pci', 'eal', 'sched']\n sources = files(\n \t'mlx5_vdpa.c',\n+\t'mlx5_vdpa_mem.c',\n )\n cflags_options = [\n \t'-std=c11',\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c\nindex 67e90fd..c67f93d 100644\n--- a/drivers/vdpa/mlx5/mlx5_vdpa.c\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c\n@@ -7,7 +7,6 @@\n #include <rte_log.h>\n #include <rte_errno.h>\n #include <rte_bus_pci.h>\n-#include <rte_vdpa.h>\n \n #include <mlx5_glue.h>\n #include <mlx5_common.h>\n@@ -15,16 +14,9 @@\n #include <mlx5_prm.h>\n \n #include \"mlx5_vdpa_utils.h\"\n+#include \"mlx5_vdpa.h\"\n \n \n-struct mlx5_vdpa_priv {\n-\tTAILQ_ENTRY(mlx5_vdpa_priv) next;\n-\tint id; /* vDPA device id. */\n-\tstruct ibv_context *ctx; /* Device context. */\n-\tstruct rte_vdpa_dev_addr dev_addr;\n-\tstruct mlx5_hca_vdpa_attr caps;\n-};\n-\n #ifndef VIRTIO_F_ORDER_PLATFORM\n #define VIRTIO_F_ORDER_PLATFORM 36\n #endif\n@@ -236,6 +228,7 @@ struct mlx5_vdpa_priv {\n \t\trte_errno = rte_errno ? rte_errno : EINVAL;\n \t\tgoto error;\n \t}\n+\tSLIST_INIT(&priv->mr_list);\n \tpthread_mutex_lock(&priv_list_lock);\n \tTAILQ_INSERT_TAIL(&priv_list, priv, next);\n \tpthread_mutex_unlock(&priv_list_lock);\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa.h b/drivers/vdpa/mlx5/mlx5_vdpa.h\nnew file mode 100644\nindex 0000000..e27baea\n--- /dev/null\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa.h\n@@ -0,0 +1,60 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2019 Mellanox Technologies, Ltd\n+ */\n+\n+#ifndef RTE_PMD_MLX5_VDPA_H_\n+#define RTE_PMD_MLX5_VDPA_H_\n+\n+#include <sys/queue.h>\n+\n+#include <rte_vdpa.h>\n+#include <rte_vhost.h>\n+\n+#include <mlx5_glue.h>\n+#include <mlx5_devx_cmds.h>\n+\n+struct mlx5_vdpa_query_mr {\n+\tSLIST_ENTRY(mlx5_vdpa_query_mr) next;\n+\tvoid *addr;\n+\tuint64_t length;\n+\tstruct mlx5dv_devx_umem *umem;\n+\tstruct mlx5_devx_obj *mkey;\n+\tint is_indirect;\n+};\n+\n+struct mlx5_vdpa_priv {\n+\tTAILQ_ENTRY(mlx5_vdpa_priv) next;\n+\tint id; /* vDPA device id. */\n+\tint vid; /* vhost device id. */\n+\tstruct ibv_context *ctx; /* Device context. */\n+\tstruct rte_vdpa_dev_addr dev_addr;\n+\tstruct mlx5_hca_vdpa_attr caps;\n+\tuint32_t pdn; /* Protection Domain number. */\n+\tstruct ibv_pd *pd;\n+\tuint32_t gpa_mkey_index;\n+\tstruct ibv_mr *null_mr;\n+\tstruct rte_vhost_memory *vmem;\n+\tSLIST_HEAD(mr_list, mlx5_vdpa_query_mr) mr_list;\n+};\n+\n+/**\n+ * Release all the prepared memory regions and all their related resources.\n+ *\n+ * @param[in] priv\n+ *   The vdpa driver private structure.\n+ */\n+void mlx5_vdpa_mem_dereg(struct mlx5_vdpa_priv *priv);\n+\n+/**\n+ * Register all the memory regions of the virtio device to the HW and allocate\n+ * all their related resources.\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_mem_register(struct mlx5_vdpa_priv *priv);\n+\n+#endif /* RTE_PMD_MLX5_VDPA_H_ */\ndiff --git a/drivers/vdpa/mlx5/mlx5_vdpa_mem.c b/drivers/vdpa/mlx5/mlx5_vdpa_mem.c\nnew file mode 100644\nindex 0000000..398ca35\n--- /dev/null\n+++ b/drivers/vdpa/mlx5/mlx5_vdpa_mem.c\n@@ -0,0 +1,346 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2019 Mellanox Technologies, Ltd\n+ */\n+#include <stdlib.h>\n+\n+#include <rte_malloc.h>\n+#include <rte_errno.h>\n+#include <rte_common.h>\n+#include <rte_sched_common.h>\n+\n+#include <mlx5_prm.h>\n+#include <mlx5_common.h>\n+\n+#include \"mlx5_vdpa_utils.h\"\n+#include \"mlx5_vdpa.h\"\n+\n+static int\n+mlx5_vdpa_pd_prepare(struct mlx5_vdpa_priv *priv)\n+{\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\tif (priv->pd)\n+\t\treturn 0;\n+\tpriv->pd = mlx5_glue->alloc_pd(priv->ctx);\n+\tif (priv->pd == NULL) {\n+\t\tDRV_LOG(ERR, \"Failed to allocate PD.\");\n+\t\treturn errno ? -errno : -ENOMEM;\n+\t}\n+\tstruct mlx5dv_obj obj;\n+\tstruct mlx5dv_pd pd_info;\n+\tint ret = 0;\n+\n+\tobj.pd.in = priv->pd;\n+\tobj.pd.out = &pd_info;\n+\tret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"Fail to get PD object info.\");\n+\t\tmlx5_glue->dealloc_pd(priv->pd);\n+\t\tpriv->pd = NULL;\n+\t\treturn -errno;\n+\t}\n+\tpriv->pdn = pd_info.pdn;\n+\treturn 0;\n+#else\n+\t(void)priv;\n+\tDRV_LOG(ERR, \"Cannot get pdn - no DV support.\");\n+\treturn -ENOTSUP;\n+#endif /* HAVE_IBV_FLOW_DV_SUPPORT */\n+}\n+\n+void\n+mlx5_vdpa_mem_dereg(struct mlx5_vdpa_priv *priv)\n+{\n+\tstruct mlx5_vdpa_query_mr *entry;\n+\tstruct mlx5_vdpa_query_mr *next;\n+\n+\tentry = SLIST_FIRST(&priv->mr_list);\n+\twhile (entry) {\n+\t\tnext = SLIST_NEXT(entry, next);\n+\t\tclaim_zero(mlx5_devx_cmd_destroy(entry->mkey));\n+\t\tif (!entry->is_indirect)\n+\t\t\tclaim_zero(mlx5_glue->devx_umem_dereg(entry->umem));\n+\t\tSLIST_REMOVE(&priv->mr_list, entry, mlx5_vdpa_query_mr, next);\n+\t\trte_free(entry);\n+\t\tentry = next;\n+\t}\n+\tSLIST_INIT(&priv->mr_list);\n+\tif (priv->null_mr) {\n+\t\tclaim_zero(mlx5_glue->dereg_mr(priv->null_mr));\n+\t\tpriv->null_mr = NULL;\n+\t}\n+\tif (priv->pd) {\n+\t\tclaim_zero(mlx5_glue->dealloc_pd(priv->pd));\n+\t\tpriv->pd = NULL;\n+\t}\n+\tif (priv->vmem) {\n+\t\tfree(priv->vmem);\n+\t\tpriv->vmem = NULL;\n+\t}\n+}\n+\n+static int\n+mlx5_vdpa_regions_addr_cmp(const void *a, const void *b)\n+{\n+\tconst struct rte_vhost_mem_region *region_a = a;\n+\tconst struct rte_vhost_mem_region *region_b = b;\n+\n+\tif (region_a->guest_phys_addr < region_b->guest_phys_addr)\n+\t\treturn -1;\n+\tif (region_a->guest_phys_addr > region_b->guest_phys_addr)\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n+#define KLM_NUM_MAX_ALIGN(sz) (RTE_ALIGN_CEIL(sz, MLX5_MAX_KLM_BYTE_COUNT) / \\\n+\t\t\t       MLX5_MAX_KLM_BYTE_COUNT)\n+\n+/*\n+ * Allocate and sort the region list and choose indirect mkey mode:\n+ *   1. Calculate GCD, guest memory size and indirect mkey entries num per mode.\n+ *   2. Align GCD to the maximum allowed size(2G) and to be power of 2.\n+ *   2. Decide the indirect mkey mode according to the next rules:\n+ *         a. If both KLM_FBS entries number and KLM entries number are bigger\n+ *            than the maximum allowed(MLX5_DEVX_MAX_KLM_ENTRIES) - error.\n+ *         b. KLM mode if KLM_FBS entries number is bigger than the maximum\n+ *            allowed(MLX5_DEVX_MAX_KLM_ENTRIES).\n+ *         c. KLM mode if GCD is smaller than the minimum allowed(4K).\n+ *         d. KLM mode if the total size of KLM entries is in one cache line\n+ *            and the total size of KLM_FBS entries is not in one cache line.\n+ *         e. Otherwise, KLM_FBS mode.\n+ */\n+static struct rte_vhost_memory *\n+mlx5_vdpa_vhost_mem_regions_prepare(int vid, uint8_t *mode, uint64_t *mem_size,\n+\t\t\t\t    uint64_t *gcd, uint32_t *entries_num)\n+{\n+\tstruct rte_vhost_memory *mem;\n+\tuint64_t size;\n+\tuint64_t klm_entries_num = 0;\n+\tuint64_t klm_fbs_entries_num;\n+\tuint32_t i;\n+\tint ret = rte_vhost_get_mem_table(vid, &mem);\n+\n+\tif (ret < 0) {\n+\t\tDRV_LOG(ERR, \"Failed to get VM memory layout vid =%d.\", vid);\n+\t\trte_errno = EINVAL;\n+\t\treturn NULL;\n+\t}\n+\tqsort(mem->regions, mem->nregions, sizeof(mem->regions[0]),\n+\t      mlx5_vdpa_regions_addr_cmp);\n+\t*mem_size = (mem->regions[(mem->nregions - 1)].guest_phys_addr) +\n+\t\t\t\t      (mem->regions[(mem->nregions - 1)].size) -\n+\t\t\t\t\t      (mem->regions[0].guest_phys_addr);\n+\t*gcd = 0;\n+\tfor (i = 0; i < mem->nregions; ++i) {\n+\t\tDRV_LOG(INFO,  \"Region %u: HVA 0x%\" PRIx64 \", GPA 0x%\" PRIx64\n+\t\t\t\", size 0x%\" PRIx64 \".\", i,\n+\t\t\tmem->regions[i].host_user_addr,\n+\t\t\tmem->regions[i].guest_phys_addr, mem->regions[i].size);\n+\t\tif (i > 0) {\n+\t\t\t/* Hole handle. */\n+\t\t\tsize = mem->regions[i].guest_phys_addr -\n+\t\t\t\t(mem->regions[i - 1].guest_phys_addr +\n+\t\t\t\t mem->regions[i - 1].size);\n+\t\t\t*gcd = rte_get_gcd(*gcd, size);\n+\t\t\tklm_entries_num += KLM_NUM_MAX_ALIGN(size);\n+\t\t}\n+\t\tsize = mem->regions[i].size;\n+\t\t*gcd = rte_get_gcd(*gcd, size);\n+\t\tklm_entries_num += KLM_NUM_MAX_ALIGN(size);\n+\t}\n+\tif (*gcd > MLX5_MAX_KLM_BYTE_COUNT)\n+\t\t*gcd = rte_get_gcd(*gcd, MLX5_MAX_KLM_BYTE_COUNT);\n+\tif (!RTE_IS_POWER_OF_2(*gcd)) {\n+\t\tuint64_t candidate_gcd = rte_align64prevpow2(*gcd);\n+\n+\t\twhile (candidate_gcd > 1 && (*gcd % candidate_gcd))\n+\t\t\tcandidate_gcd /= 2;\n+\t\tDRV_LOG(DEBUG, \"GCD 0x%\" PRIx64 \" is not power of 2. Adjusted \"\n+\t\t\t\"GCD is 0x%\" PRIx64 \".\", *gcd, candidate_gcd);\n+\t\t*gcd = candidate_gcd;\n+\t}\n+\tklm_fbs_entries_num = *mem_size / *gcd;\n+\tif (*gcd < MLX5_MIN_KLM_FIXED_BUFFER_SIZE || klm_fbs_entries_num >\n+\t    MLX5_DEVX_MAX_KLM_ENTRIES ||\n+\t    ((klm_entries_num * sizeof(struct mlx5_klm)) <=\n+\t    RTE_CACHE_LINE_SIZE && (klm_fbs_entries_num *\n+\t\t\t\t    sizeof(struct mlx5_klm)) >\n+\t\t\t\t\t\t\tRTE_CACHE_LINE_SIZE)) {\n+\t\t*mode = MLX5_MKC_ACCESS_MODE_KLM;\n+\t\t*entries_num = klm_entries_num;\n+\t\tDRV_LOG(INFO, \"Indirect mkey mode is KLM.\");\n+\t} else {\n+\t\t*mode = MLX5_MKC_ACCESS_MODE_KLM_FBS;\n+\t\t*entries_num = klm_fbs_entries_num;\n+\t\tDRV_LOG(INFO, \"Indirect mkey mode is KLM Fixed Buffer Size.\");\n+\t}\n+\tDRV_LOG(DEBUG, \"Memory registration information: nregions = %u, \"\n+\t\t\"mem_size = 0x%\" PRIx64 \", GCD = 0x%\" PRIx64\n+\t\t\", klm_fbs_entries_num = 0x%\" PRIx64 \", klm_entries_num = 0x%\"\n+\t\tPRIx64 \".\", mem->nregions, *mem_size, *gcd, klm_fbs_entries_num,\n+\t\tklm_entries_num);\n+\tif (*entries_num > MLX5_DEVX_MAX_KLM_ENTRIES) {\n+\t\tDRV_LOG(ERR, \"Failed to prepare memory of vid %d - memory is \"\n+\t\t\t\"too fragmented.\", vid);\n+\t\tfree(mem);\n+\t\treturn NULL;\n+\t}\n+\treturn mem;\n+}\n+\n+#define KLM_SIZE_MAX_ALIGN(sz) ((sz) > MLX5_MAX_KLM_BYTE_COUNT ? \\\n+\t\t\t\tMLX5_MAX_KLM_BYTE_COUNT : (sz))\n+\n+/*\n+ * The target here is to group all the physical memory regions of the\n+ * virtio device in one indirect mkey.\n+ * For KLM Fixed Buffer Size mode (HW find the translation entry in one\n+ * read according to the guest phisical address):\n+ * All the sub-direct mkeys of it must be in the same size, hence, each\n+ * one of them should be in the GCD size of all the virtio memory\n+ * regions and the holes between them.\n+ * For KLM mode (each entry may be in different size so HW must iterate\n+ * the entries):\n+ * Each virtio memory region and each hole between them have one entry,\n+ * just need to cover the maximum allowed size(2G) by splitting entries\n+ * which their associated memory regions are bigger than 2G.\n+ * It means that each virtio memory region may be mapped to more than\n+ * one direct mkey in the 2 modes.\n+ * All the holes of invalid memory between the virtio memory regions\n+ * will be mapped to the null memory region for security.\n+ */\n+int\n+mlx5_vdpa_mem_register(struct mlx5_vdpa_priv *priv)\n+{\n+\tstruct mlx5_devx_mkey_attr mkey_attr;\n+\tstruct mlx5_vdpa_query_mr *entry = NULL;\n+\tstruct rte_vhost_mem_region *reg = NULL;\n+\tuint8_t mode;\n+\tuint32_t entries_num = 0;\n+\tuint32_t i;\n+\tuint64_t gcd;\n+\tuint64_t klm_size;\n+\tuint64_t mem_size;\n+\tuint64_t k;\n+\tint klm_index = 0;\n+\tint ret;\n+\tstruct rte_vhost_memory *mem = mlx5_vdpa_vhost_mem_regions_prepare\n+\t\t\t      (priv->vid, &mode, &mem_size, &gcd, &entries_num);\n+\tstruct mlx5_klm klm_array[entries_num];\n+\n+\tif (!mem)\n+\t\treturn -rte_errno;\n+\tpriv->vmem = mem;\n+\tret = mlx5_vdpa_pd_prepare(priv);\n+\tif (ret)\n+\t\tgoto error;\n+\tpriv->null_mr = mlx5_glue->alloc_null_mr(priv->pd);\n+\tif (!priv->null_mr) {\n+\t\tDRV_LOG(ERR, \"Failed to allocate null MR.\");\n+\t\tret = -errno;\n+\t\tgoto error;\n+\t}\n+\tDRV_LOG(DEBUG, \"Dump fill Mkey = %u.\", priv->null_mr->lkey);\n+\tfor (i = 0; i < mem->nregions; i++) {\n+\t\treg = &mem->regions[i];\n+\t\tentry = rte_zmalloc(__func__, sizeof(*entry), 0);\n+\t\tif (!entry) {\n+\t\t\tret = -ENOMEM;\n+\t\t\tDRV_LOG(ERR, \"Failed to allocate mem entry memory.\");\n+\t\t\tgoto error;\n+\t\t}\n+\t\tentry->umem = mlx5_glue->devx_umem_reg(priv->ctx,\n+\t\t\t\t\t (void *)(uintptr_t)reg->host_user_addr,\n+\t\t\t\t\t     reg->size, IBV_ACCESS_LOCAL_WRITE);\n+\t\tif (!entry->umem) {\n+\t\t\tDRV_LOG(ERR, \"Failed to register Umem by Devx.\");\n+\t\t\tret = -errno;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tmkey_attr.addr = (uintptr_t)(reg->guest_phys_addr);\n+\t\tmkey_attr.size = reg->size;\n+\t\tmkey_attr.umem_id = entry->umem->umem_id;\n+\t\tmkey_attr.pd = priv->pdn;\n+\t\tmkey_attr.pg_access = 1;\n+\t\tmkey_attr.klm_array = NULL;\n+\t\tmkey_attr.klm_num = 0;\n+\t\tentry->mkey = mlx5_devx_cmd_mkey_create(priv->ctx, &mkey_attr);\n+\t\tif (!entry->mkey) {\n+\t\t\tDRV_LOG(ERR, \"Failed to create direct Mkey.\");\n+\t\t\tret = -rte_errno;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tentry->addr = (void *)(uintptr_t)(reg->host_user_addr);\n+\t\tentry->length = reg->size;\n+\t\tentry->is_indirect = 0;\n+\t\tif (i > 0) {\n+\t\t\tuint64_t sadd;\n+\t\t\tuint64_t empty_region_sz = reg->guest_phys_addr -\n+\t\t\t\t\t  (mem->regions[i - 1].guest_phys_addr +\n+\t\t\t\t\t   mem->regions[i - 1].size);\n+\n+\t\t\tif (empty_region_sz > 0) {\n+\t\t\t\tsadd = mem->regions[i - 1].guest_phys_addr +\n+\t\t\t\t       mem->regions[i - 1].size;\n+\t\t\t\tklm_size = mode == MLX5_MKC_ACCESS_MODE_KLM ?\n+\t\t\t\t      KLM_SIZE_MAX_ALIGN(empty_region_sz) : gcd;\n+\t\t\t\tfor (k = 0; k < empty_region_sz;\n+\t\t\t\t     k += klm_size) {\n+\t\t\t\t\tklm_array[klm_index].byte_count =\n+\t\t\t\t\t\tk + klm_size > empty_region_sz ?\n+\t\t\t\t\t\t empty_region_sz - k : klm_size;\n+\t\t\t\t\tklm_array[klm_index].mkey =\n+\t\t\t\t\t\t\t    priv->null_mr->lkey;\n+\t\t\t\t\tklm_array[klm_index].address = sadd + k;\n+\t\t\t\t\tklm_index++;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tklm_size = mode == MLX5_MKC_ACCESS_MODE_KLM ?\n+\t\t\t\t\t    KLM_SIZE_MAX_ALIGN(reg->size) : gcd;\n+\t\tfor (k = 0; k < reg->size; k += klm_size) {\n+\t\t\tklm_array[klm_index].byte_count = k + klm_size >\n+\t\t\t\t\t   reg->size ? reg->size - k : klm_size;\n+\t\t\tklm_array[klm_index].mkey = entry->mkey->id;\n+\t\t\tklm_array[klm_index].address = reg->guest_phys_addr + k;\n+\t\t\tklm_index++;\n+\t\t}\n+\t\tSLIST_INSERT_HEAD(&priv->mr_list, entry, next);\n+\t}\n+\tmkey_attr.addr = (uintptr_t)(mem->regions[0].guest_phys_addr);\n+\tmkey_attr.size = mem_size;\n+\tmkey_attr.pd = priv->pdn;\n+\tmkey_attr.umem_id = 0;\n+\t/* Must be zero for KLM mode. */\n+\tmkey_attr.log_entity_size = mode == MLX5_MKC_ACCESS_MODE_KLM_FBS ?\n+\t\t\t\t\t\t\t  rte_log2_u64(gcd) : 0;\n+\tmkey_attr.pg_access = 0;\n+\tmkey_attr.klm_array = klm_array;\n+\tmkey_attr.klm_num = klm_index;\n+\tentry = rte_zmalloc(__func__, sizeof(*entry), 0);\n+\tif (!entry) {\n+\t\tDRV_LOG(ERR, \"Failed to allocate memory for indirect entry.\");\n+\t\tret = -ENOMEM;\n+\t\tgoto error;\n+\t}\n+\tentry->mkey = mlx5_devx_cmd_mkey_create(priv->ctx, &mkey_attr);\n+\tif (!entry->mkey) {\n+\t\tDRV_LOG(ERR, \"Failed to create indirect Mkey.\");\n+\t\tret = -rte_errno;\n+\t\tgoto error;\n+\t}\n+\tentry->is_indirect = 1;\n+\tSLIST_INSERT_HEAD(&priv->mr_list, entry, next);\n+\tpriv->gpa_mkey_index = entry->mkey->id;\n+\treturn 0;\n+error:\n+\tif (entry) {\n+\t\tif (entry->mkey)\n+\t\t\tmlx5_devx_cmd_destroy(entry->mkey);\n+\t\tif (entry->umem)\n+\t\t\tmlx5_glue->devx_umem_dereg(entry->umem);\n+\t\trte_free(entry);\n+\t}\n+\tmlx5_vdpa_mem_dereg(priv);\n+\trte_errno = -ret;\n+\treturn ret;\n+}\n",
    "prefixes": [
        "v2",
        "04/13"
    ]
}