get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 52522,
    "url": "http://patches.dpdk.org/api/patches/52522/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190409231324.35715-5-yskoh@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": "<20190409231324.35715-5-yskoh@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190409231324.35715-5-yskoh@mellanox.com",
    "date": "2019-04-09T23:13:24",
    "name": "[v4,4/4] net/mlx4: remove device register remap",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2acdaf5dd68b2f14b7fe965e296a3b107c415577",
    "submitter": {
        "id": 636,
        "url": "http://patches.dpdk.org/api/people/636/?format=api",
        "name": "Yongseok Koh",
        "email": "yskoh@mellanox.com"
    },
    "delegate": {
        "id": 6624,
        "url": "http://patches.dpdk.org/api/users/6624/?format=api",
        "username": "shahafs",
        "first_name": "Shahaf",
        "last_name": "Shuler",
        "email": "shahafs@mellanox.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190409231324.35715-5-yskoh@mellanox.com/mbox/",
    "series": [
        {
            "id": 4218,
            "url": "http://patches.dpdk.org/api/series/4218/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4218",
            "date": "2019-04-09T23:13:20",
            "name": "net/mlx: remove device register remap",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/4218/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/52522/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/52522/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B410D5F2A;\n\tWed, 10 Apr 2019 01:13:47 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n\tby dpdk.org (Postfix) with ESMTP id E7FA95942\n\tfor <dev@dpdk.org>; Wed, 10 Apr 2019 01:13:34 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n\tyskoh@mellanox.com)\n\twith ESMTPS (AES256-SHA encrypted); 10 Apr 2019 02:13:33 +0300",
            "from scfae-sc-2.mti.labs.mlnx (scfae-sc-2.mti.labs.mlnx\n\t[10.101.0.96])\n\tby labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x39NDP5c004967;\n\tWed, 10 Apr 2019 02:13:32 +0300"
        ],
        "From": "Yongseok Koh <yskoh@mellanox.com>",
        "To": "shahafs@mellanox.com",
        "Cc": "dev@dpdk.org",
        "Date": "Tue,  9 Apr 2019 16:13:24 -0700",
        "Message-Id": "<20190409231324.35715-5-yskoh@mellanox.com>",
        "X-Mailer": "git-send-email 2.11.0",
        "In-Reply-To": "<20190409231324.35715-1-yskoh@mellanox.com>",
        "References": "<20190325193627.19726-1-yskoh@mellanox.com>\n\t<20190409231324.35715-1-yskoh@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v4 4/4] net/mlx4: remove device register remap",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "UAR (User Access Region) register does not need to be remapped for primary\nprocess but it should be remapped only for secondary process. UAR register\ntable is in the process private structure in rte_eth_devices[],\n\t(struct mlx4_proc_priv *)rte_eth_devices[port_id].process_private\n\nThe actual UAR table follows the data structure and the table is used for\nboth Tx and Rx.\n\nFor Tx, BlueFlame in UAR is used to ring the doorbell. MLX4_TX_BFREG(txq)\nis defined to get a register for the txq. Processes access its own private\ndata to acquire the register from the UAR table.\n\nFor Rx, the doorbell in UAR is required in arming CQ event. However, it is\na known issue that the register isn't remapped for secondary process.\n\nSigned-off-by: Yongseok Koh <yskoh@mellanox.com>\n---\n drivers/net/mlx4/mlx4.c      | 255 +++++++++++--------------------------------\n drivers/net/mlx4/mlx4.h      |  15 ++-\n drivers/net/mlx4/mlx4_prm.h  |   3 +-\n drivers/net/mlx4/mlx4_rxtx.c |   2 +-\n drivers/net/mlx4/mlx4_rxtx.h |   6 +-\n drivers/net/mlx4/mlx4_txq.c  | 170 ++++++++++++++++++-----------\n 6 files changed, 183 insertions(+), 268 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c\nindex 9bca0ce9cd..17dfcd5a3b 100644\n--- a/drivers/net/mlx4/mlx4.c\n+++ b/drivers/net/mlx4/mlx4.c\n@@ -126,30 +126,6 @@ mlx4_init_shared_data(void)\n \treturn ret;\n }\n \n-/**\n- * Uninitialize shared data between primary and secondary process.\n- *\n- * The pointer of secondary process is dereferenced and primary process frees\n- * the memzone.\n- */\n-static void\n-mlx4_uninit_shared_data(void)\n-{\n-\tconst struct rte_memzone *mz;\n-\n-\trte_spinlock_lock(&mlx4_shared_data_lock);\n-\tif (mlx4_shared_data) {\n-\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY) {\n-\t\t\tmz = rte_memzone_lookup(MZ_MLX4_PMD_SHARED_DATA);\n-\t\t\trte_memzone_free(mz);\n-\t\t} else {\n-\t\t\tmemset(&mlx4_local_data, 0, sizeof(mlx4_local_data));\n-\t\t}\n-\t\tmlx4_shared_data = NULL;\n-\t}\n-\trte_spinlock_unlock(&mlx4_shared_data_lock);\n-}\n-\n #ifdef HAVE_IBV_MLX4_BUF_ALLOCATORS\n /**\n  * Verbs callback to allocate a memory. This function should allocate the space\n@@ -207,6 +183,53 @@ mlx4_free_verbs_buf(void *ptr, void *data __rte_unused)\n #endif\n \n /**\n+ * Initialize process private data structure.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx4_proc_priv_init(struct rte_eth_dev *dev)\n+{\n+\tstruct mlx4_proc_priv *ppriv;\n+\tsize_t ppriv_size;\n+\n+\t/*\n+\t * UAR register table follows the process private structure. BlueFlame\n+\t * registers for Tx queues are stored in the table.\n+\t */\n+\tppriv_size = sizeof(struct mlx4_proc_priv) +\n+\t\t     dev->data->nb_tx_queues * sizeof(void *);\n+\tppriv = rte_malloc_socket(\"mlx4_proc_priv\", ppriv_size,\n+\t\t\t\t  RTE_CACHE_LINE_SIZE, dev->device->numa_node);\n+\tif (!ppriv) {\n+\t\trte_errno = ENOMEM;\n+\t\treturn -rte_errno;\n+\t}\n+\tppriv->uar_table_sz = ppriv_size;\n+\tdev->process_private = ppriv;\n+\treturn 0;\n+}\n+\n+/**\n+ * Un-initialize process private data structure.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device structure.\n+ */\n+static void\n+mlx4_proc_priv_uninit(struct rte_eth_dev *dev)\n+{\n+\tif (!dev->process_private)\n+\t\treturn;\n+\trte_free(dev->process_private);\n+\tdev->process_private = NULL;\n+}\n+\n+/**\n  * DPDK callback for Ethernet device configuration.\n  *\n  * @param dev\n@@ -232,9 +255,17 @@ mlx4_dev_configure(struct rte_eth_dev *dev)\n \t\tgoto exit;\n \t}\n \tret = mlx4_intr_install(priv);\n-\tif (ret)\n+\tif (ret) {\n \t\tERROR(\"%p: interrupt handler installation failed\",\n \t\t      (void *)dev);\n+\t\tgoto exit;\n+\t}\n+\tret = mlx4_proc_priv_init(dev);\n+\tif (ret) {\n+\t\tERROR(\"%p: process private data allocation failed\",\n+\t\t      (void *)dev);\n+\t\tgoto exit;\n+\t}\n exit:\n \treturn ret;\n }\n@@ -262,11 +293,6 @@ mlx4_dev_start(struct rte_eth_dev *dev)\n \t\treturn 0;\n \tDEBUG(\"%p: attaching configured flows to all RX queues\", (void *)dev);\n \tpriv->started = 1;\n-\tret = mlx4_tx_uar_remap(dev, priv->ctx->cmd_fd);\n-\tif (ret) {\n-\t\tERROR(\"%p: cannot remap UAR\", (void *)dev);\n-\t\tgoto err;\n-\t}\n \tret = mlx4_rss_init(priv);\n \tif (ret) {\n \t\tERROR(\"%p: cannot initialize RSS resources: %s\",\n@@ -314,10 +340,6 @@ static void\n mlx4_dev_stop(struct rte_eth_dev *dev)\n {\n \tstruct mlx4_priv *priv = dev->data->dev_private;\n-#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET\n-\tconst size_t page_size = sysconf(_SC_PAGESIZE);\n-\tint i;\n-#endif\n \n \tif (!priv->started)\n \t\treturn;\n@@ -331,17 +353,6 @@ mlx4_dev_stop(struct rte_eth_dev *dev)\n \tmlx4_flow_sync(priv, NULL);\n \tmlx4_rxq_intr_disable(priv);\n \tmlx4_rss_deinit(priv);\n-#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET\n-\tfor (i = 0; i != dev->data->nb_tx_queues; ++i) {\n-\t\tstruct txq *txq;\n-\n-\t\ttxq = dev->data->tx_queues[i];\n-\t\tif (!txq)\n-\t\t\tcontinue;\n-\t\tmunmap((void *)RTE_ALIGN_FLOOR((uintptr_t)txq->msq.db,\n-\t\t\t\t\t       page_size), page_size);\n-\t}\n-#endif\n }\n \n /**\n@@ -372,6 +383,7 @@ mlx4_dev_close(struct rte_eth_dev *dev)\n \t\tmlx4_rx_queue_release(dev->data->rx_queues[i]);\n \tfor (i = 0; i != dev->data->nb_tx_queues; ++i)\n \t\tmlx4_tx_queue_release(dev->data->tx_queues[i]);\n+\tmlx4_proc_priv_uninit(dev);\n \tmlx4_mr_release(dev);\n \tif (priv->pd != NULL) {\n \t\tassert(priv->ctx != NULL);\n@@ -666,130 +678,6 @@ mlx4_hw_rss_sup(struct ibv_context *ctx, struct ibv_pd *pd,\n \n static struct rte_pci_driver mlx4_driver;\n \n-static int\n-find_lower_va_bound(const struct rte_memseg_list *msl,\n-\t\tconst struct rte_memseg *ms, void *arg)\n-{\n-\tvoid **addr = arg;\n-\n-\tif (msl->external)\n-\t\treturn 0;\n-\tif (*addr == NULL)\n-\t\t*addr = ms->addr;\n-\telse\n-\t\t*addr = RTE_MIN(*addr, ms->addr);\n-\n-\treturn 0;\n-}\n-\n-/**\n- * Reserve UAR address space for primary process.\n- *\n- * Process local resource is used by both primary and secondary to avoid\n- * duplicate reservation. The space has to be available on both primary and\n- * secondary process, TXQ UAR maps to this area using fixed mmap w/o double\n- * check.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx4_uar_init_primary(void)\n-{\n-\tstruct mlx4_shared_data *sd = mlx4_shared_data;\n-\tvoid *addr = (void *)0;\n-\n-\tif (sd->uar_base)\n-\t\treturn 0;\n-\t/* find out lower bound of hugepage segments */\n-\trte_memseg_walk(find_lower_va_bound, &addr);\n-\t/* keep distance to hugepages to minimize potential conflicts. */\n-\taddr = RTE_PTR_SUB(addr, (uintptr_t)(MLX4_UAR_OFFSET + MLX4_UAR_SIZE));\n-\t/* anonymous mmap, no real memory consumption. */\n-\taddr = mmap(addr, MLX4_UAR_SIZE,\n-\t\t    PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n-\tif (addr == MAP_FAILED) {\n-\t\tERROR(\"failed to reserve UAR address space, please\"\n-\t\t      \" adjust MLX4_UAR_SIZE or try --base-virtaddr\");\n-\t\trte_errno = ENOMEM;\n-\t\treturn -rte_errno;\n-\t}\n-\t/* Accept either same addr or a new addr returned from mmap if target\n-\t * range occupied.\n-\t */\n-\tINFO(\"reserved UAR address space: %p\", addr);\n-\tsd->uar_base = addr; /* for primary and secondary UAR re-mmap. */\n-\treturn 0;\n-}\n-\n-/**\n- * Unmap UAR address space reserved for primary process.\n- */\n-static void\n-mlx4_uar_uninit_primary(void)\n-{\n-\tstruct mlx4_shared_data *sd = mlx4_shared_data;\n-\n-\tif (!sd->uar_base)\n-\t\treturn;\n-\tmunmap(sd->uar_base, MLX4_UAR_SIZE);\n-\tsd->uar_base = NULL;\n-}\n-\n-/**\n- * Reserve UAR address space for secondary process, align with primary process.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx4_uar_init_secondary(void)\n-{\n-\tstruct mlx4_shared_data *sd = mlx4_shared_data;\n-\tstruct mlx4_local_data *ld = &mlx4_local_data;\n-\tvoid *addr;\n-\n-\tif (ld->uar_base) { /* Already reserved. */\n-\t\tassert(sd->uar_base == ld->uar_base);\n-\t\treturn 0;\n-\t}\n-\tassert(sd->uar_base);\n-\t/* anonymous mmap, no real memory consumption. */\n-\taddr = mmap(sd->uar_base, MLX4_UAR_SIZE,\n-\t\t    PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n-\tif (addr == MAP_FAILED) {\n-\t\tERROR(\"UAR mmap failed: %p size: %llu\",\n-\t\t      sd->uar_base, MLX4_UAR_SIZE);\n-\t\trte_errno = ENXIO;\n-\t\treturn -rte_errno;\n-\t}\n-\tif (sd->uar_base != addr) {\n-\t\tERROR(\"UAR address %p size %llu occupied, please\"\n-\t\t      \" adjust MLX4_UAR_OFFSET or try EAL parameter\"\n-\t\t      \" --base-virtaddr\",\n-\t\t      sd->uar_base, MLX4_UAR_SIZE);\n-\t\trte_errno = ENXIO;\n-\t\treturn -rte_errno;\n-\t}\n-\tld->uar_base = addr;\n-\tINFO(\"reserved UAR address space: %p\", addr);\n-\treturn 0;\n-}\n-\n-/**\n- * Unmap UAR address space reserved for secondary process.\n- */\n-static void\n-mlx4_uar_uninit_secondary(void)\n-{\n-\tstruct mlx4_local_data *ld = &mlx4_local_data;\n-\n-\tif (!ld->uar_base)\n-\t\treturn;\n-\tmunmap(ld->uar_base, MLX4_UAR_SIZE);\n-\tld->uar_base = NULL;\n-}\n-\n /**\n  * PMD global initialization.\n  *\n@@ -805,7 +693,6 @@ mlx4_init_once(void)\n {\n \tstruct mlx4_shared_data *sd;\n \tstruct mlx4_local_data *ld = &mlx4_local_data;\n-\tint ret;\n \n \tif (mlx4_init_shared_data())\n \t\treturn -rte_errno;\n@@ -821,18 +708,12 @@ mlx4_init_once(void)\n \t\trte_mem_event_callback_register(\"MLX4_MEM_EVENT_CB\",\n \t\t\t\t\t\tmlx4_mr_mem_event_cb, NULL);\n \t\tmlx4_mp_init_primary();\n-\t\tret = mlx4_uar_init_primary();\n-\t\tif (ret)\n-\t\t\tgoto error;\n \t\tsd->init_done = true;\n \t\tbreak;\n \tcase RTE_PROC_SECONDARY:\n \t\tif (ld->init_done)\n \t\t\tbreak;\n \t\tmlx4_mp_init_secondary();\n-\t\tret = mlx4_uar_init_secondary();\n-\t\tif (ret)\n-\t\t\tgoto error;\n \t\t++sd->secondary_cnt;\n \t\tld->init_done = true;\n \t\tbreak;\n@@ -841,23 +722,6 @@ mlx4_init_once(void)\n \t}\n \trte_spinlock_unlock(&sd->lock);\n \treturn 0;\n-error:\n-\tswitch (rte_eal_process_type()) {\n-\tcase RTE_PROC_PRIMARY:\n-\t\tmlx4_uar_uninit_primary();\n-\t\tmlx4_mp_uninit_primary();\n-\t\trte_mem_event_callback_unregister(\"MLX4_MEM_EVENT_CB\", NULL);\n-\t\tbreak;\n-\tcase RTE_PROC_SECONDARY:\n-\t\tmlx4_uar_uninit_secondary();\n-\t\tmlx4_mp_uninit_secondary();\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\trte_spinlock_unlock(&sd->lock);\n-\tmlx4_uninit_shared_data();\n-\treturn -rte_errno;\n }\n \n /**\n@@ -1009,6 +873,9 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)\n \t\t\t}\n \t\t\teth_dev->device = &pci_dev->device;\n \t\t\teth_dev->dev_ops = &mlx4_dev_sec_ops;\n+\t\t\terr = mlx4_proc_priv_init(eth_dev);\n+\t\t\tif (err)\n+\t\t\t\tgoto error;\n \t\t\t/* Receive command fd from primary process. */\n \t\t\terr = mlx4_mp_req_verbs_cmd_fd(eth_dev);\n \t\t\tif (err < 0) {\n@@ -1016,7 +883,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)\n \t\t\t\tgoto error;\n \t\t\t}\n \t\t\t/* Remap UAR for Tx queues. */\n-\t\t\terr = mlx4_tx_uar_remap(eth_dev, err);\n+\t\t\terr = mlx4_tx_uar_init_secondary(eth_dev, err);\n \t\t\tif (err) {\n \t\t\t\terr = rte_errno;\n \t\t\t\tgoto error;\ndiff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h\nindex 1db23d6cc9..904c4f5c03 100644\n--- a/drivers/net/mlx4/mlx4.h\n+++ b/drivers/net/mlx4/mlx4.h\n@@ -138,8 +138,6 @@ struct mlx4_shared_data {\n \t/* Global spinlock for primary and secondary processes. */\n \tint init_done; /* Whether primary has done initialization. */\n \tunsigned int secondary_cnt; /* Number of secondary processes init'd. */\n-\tvoid *uar_base;\n-\t/* Reserved UAR address space for TXQ UAR(hw doorbell) mapping. */\n \tstruct mlx4_dev_list mem_event_cb_list;\n \trte_rwlock_t mem_event_rwlock;\n };\n@@ -147,12 +145,21 @@ struct mlx4_shared_data {\n /* Per-process data structure, not visible to other processes. */\n struct mlx4_local_data {\n \tint init_done; /* Whether a secondary has done initialization. */\n-\tvoid *uar_base;\n-\t/* Reserved UAR address space for TXQ UAR(hw doorbell) mapping. */\n };\n \n extern struct mlx4_shared_data *mlx4_shared_data;\n \n+/* Per-process private structure. */\n+struct mlx4_proc_priv {\n+\tsize_t uar_table_sz;\n+\t/* Size of UAR register table. */\n+\tvoid *uar_table[];\n+\t/* Table of UAR registers for each process. */\n+};\n+\n+#define MLX4_PROC_PRIV(port_id) \\\n+\t((struct mlx4_proc_priv *)rte_eth_devices[port_id].process_private)\n+\n /** Private data structure. */\n struct mlx4_priv {\n \tLIST_ENTRY(mlx4_priv) mem_event_cb;\ndiff --git a/drivers/net/mlx4/mlx4_prm.h b/drivers/net/mlx4/mlx4_prm.h\nindex b3e11dde25..16ae6db82d 100644\n--- a/drivers/net/mlx4/mlx4_prm.h\n+++ b/drivers/net/mlx4/mlx4_prm.h\n@@ -77,8 +77,7 @@ struct mlx4_sq {\n \tuint32_t owner_opcode;\n \t/**< Default owner opcode with HW valid owner bit. */\n \tuint32_t stamp; /**< Stamp value with an invalid HW owner bit. */\n-\tvolatile uint32_t *qp_sdb; /**< Pointer to the doorbell. */\n-\tvolatile uint32_t *db; /**< Pointer to the doorbell remapped. */\n+\tuint32_t *db; /**< Pointer to the doorbell. */\n \toff_t uar_mmap_offset; /* UAR mmap offset for non-primary process. */\n \tuint32_t doorbell_qpn; /**< qp number to write to the doorbell. */\n };\ndiff --git a/drivers/net/mlx4/mlx4_rxtx.c b/drivers/net/mlx4/mlx4_rxtx.c\nindex f22f1ba559..391271a616 100644\n--- a/drivers/net/mlx4/mlx4_rxtx.c\n+++ b/drivers/net/mlx4/mlx4_rxtx.c\n@@ -1048,7 +1048,7 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)\n \t/* Make sure that descriptors are written before doorbell record. */\n \trte_wmb();\n \t/* Ring QP doorbell. */\n-\trte_write32(txq->msq.doorbell_qpn, txq->msq.db);\n+\trte_write32(txq->msq.doorbell_qpn, MLX4_TX_BFREG(txq));\n \ttxq->elts_head += i;\n \treturn i;\n }\ndiff --git a/drivers/net/mlx4/mlx4_rxtx.h b/drivers/net/mlx4/mlx4_rxtx.h\nindex 7d7a8988ed..8baf33fa94 100644\n--- a/drivers/net/mlx4/mlx4_rxtx.h\n+++ b/drivers/net/mlx4/mlx4_rxtx.h\n@@ -97,6 +97,7 @@ struct mlx4_txq_stats {\n struct txq {\n \tstruct mlx4_sq msq; /**< Info for directly manipulating the SQ. */\n \tstruct mlx4_cq mcq; /**< Info for directly manipulating the CQ. */\n+\tuint16_t port_id; /**< Port ID of device. */\n \tunsigned int elts_head; /**< Current index in (*elts)[]. */\n \tunsigned int elts_tail; /**< First element awaiting completion. */\n \tint elts_comp_cd; /**< Countdown for next completion. */\n@@ -118,6 +119,9 @@ struct txq {\n \tuint8_t data[]; /**< Remaining queue resources. */\n };\n \n+#define MLX4_TX_BFREG(txq) \\\n+\t\t(MLX4_PROC_PRIV((txq)->port_id)->uar_table[(txq)->stats.idx])\n+\n /* mlx4_rxq.c */\n \n uint8_t mlx4_rss_hash_key_default[MLX4_RSS_HASH_KEY_SIZE];\n@@ -152,7 +156,7 @@ uint16_t mlx4_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,\n \n /* mlx4_txq.c */\n \n-int mlx4_tx_uar_remap(struct rte_eth_dev *dev, int fd);\n+int mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd);\n uint64_t mlx4_get_tx_port_offloads(struct mlx4_priv *priv);\n int mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx,\n \t\t\tuint16_t desc, unsigned int socket,\ndiff --git a/drivers/net/mlx4/mlx4_txq.c b/drivers/net/mlx4/mlx4_txq.c\nindex 698a648c8d..01a5efd80d 100644\n--- a/drivers/net/mlx4/mlx4_txq.c\n+++ b/drivers/net/mlx4/mlx4_txq.c\n@@ -40,11 +40,88 @@\n #include \"mlx4_utils.h\"\n \n /**\n- * Mmap TX UAR(HW doorbell) pages into reserved UAR address space.\n- * Both primary and secondary process do mmap to make UAR address\n- * aligned.\n+ * Initialize Tx UAR registers for primary process.\n  *\n- * @param[in] dev\n+ * @param txq\n+ *   Pointer to Tx queue structure.\n+ */\n+static void\n+txq_uar_init(struct txq *txq)\n+{\n+\tstruct mlx4_priv *priv = txq->priv;\n+\tstruct mlx4_proc_priv *ppriv = MLX4_PROC_PRIV(PORT_ID(priv));\n+\n+\tassert(rte_eal_process_type() == RTE_PROC_PRIMARY);\n+\tassert(ppriv);\n+\tppriv->uar_table[txq->stats.idx] = txq->msq.db;\n+}\n+\n+#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET\n+/**\n+ * Remap UAR register of a Tx queue for secondary process.\n+ *\n+ * Remapped address is stored at the table in the process private structure of\n+ * the device, indexed by queue index.\n+ *\n+ * @param txq\n+ *   Pointer to Tx queue structure.\n+ * @param fd\n+ *   Verbs file descriptor to map UAR pages.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+txq_uar_init_secondary(struct txq *txq, int fd)\n+{\n+\tstruct mlx4_priv *priv = txq->priv;\n+\tstruct mlx4_proc_priv *ppriv = MLX4_PROC_PRIV(PORT_ID(priv));\n+\tvoid *addr;\n+\tuintptr_t uar_va;\n+\tuintptr_t offset;\n+\tconst size_t page_size = sysconf(_SC_PAGESIZE);\n+\n+\tassert(ppriv);\n+\t/*\n+\t * As rdma-core, UARs are mapped in size of OS page\n+\t * size. Ref to libmlx4 function: mlx4_init_context()\n+\t */\n+\tuar_va = (uintptr_t)txq->msq.db;\n+\toffset = uar_va & (page_size - 1); /* Offset in page. */\n+\taddr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, fd,\n+\t\t\ttxq->msq.uar_mmap_offset);\n+\tif (addr == MAP_FAILED) {\n+\t\tERROR(\"port %u mmap failed for BF reg of txq %u\",\n+\t\t      txq->port_id, txq->stats.idx);\n+\t\trte_errno = ENXIO;\n+\t\treturn -rte_errno;\n+\t}\n+\taddr = RTE_PTR_ADD(addr, offset);\n+\tppriv->uar_table[txq->stats.idx] = addr;\n+\treturn 0;\n+}\n+\n+/**\n+ * Unmap UAR register of a Tx queue for secondary process.\n+ *\n+ * @param txq\n+ *   Pointer to Tx queue structure.\n+ */\n+static void\n+txq_uar_uninit_secondary(struct txq *txq)\n+{\n+\tstruct mlx4_proc_priv *ppriv = MLX4_PROC_PRIV(PORT_ID(txq->priv));\n+\tconst size_t page_size = sysconf(_SC_PAGESIZE);\n+\tvoid *addr;\n+\n+\taddr = ppriv->uar_table[txq->stats.idx];\n+\tmunmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);\n+}\n+\n+/**\n+ * Initialize Tx UAR registers for secondary process.\n+ *\n+ * @param dev\n  *   Pointer to Ethernet device.\n  * @param fd\n  *   Verbs file descriptor to map UAR pages.\n@@ -52,81 +129,41 @@\n  * @return\n  *   0 on success, a negative errno value otherwise and rte_errno is set.\n  */\n-#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET\n int\n-mlx4_tx_uar_remap(struct rte_eth_dev *dev, int fd)\n+mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)\n {\n-\tunsigned int i, j;\n \tconst unsigned int txqs_n = dev->data->nb_tx_queues;\n-\tuintptr_t pages[txqs_n];\n-\tunsigned int pages_n = 0;\n-\tuintptr_t uar_va;\n-\tuintptr_t off;\n-\tvoid *addr;\n-\tvoid *ret;\n \tstruct txq *txq;\n-\tint already_mapped;\n-\tsize_t page_size = sysconf(_SC_PAGESIZE);\n+\tunsigned int i;\n+\tint ret;\n \n-\tmemset(pages, 0, txqs_n * sizeof(uintptr_t));\n-\t/*\n-\t * As rdma-core, UARs are mapped in size of OS page size.\n-\t * Use aligned address to avoid duplicate mmap.\n-\t * Ref to libmlx4 function: mlx4_init_context()\n-\t */\n+\tassert(rte_eal_process_type() == RTE_PROC_SECONDARY);\n \tfor (i = 0; i != txqs_n; ++i) {\n \t\ttxq = dev->data->tx_queues[i];\n \t\tif (!txq)\n \t\t\tcontinue;\n-\t\t/* UAR addr form verbs used to find dup and offset in page. */\n-\t\tuar_va = (uintptr_t)txq->msq.qp_sdb;\n-\t\toff = uar_va & (page_size - 1); /* offset in page. */\n-\t\tuar_va = RTE_ALIGN_FLOOR(uar_va, page_size); /* page addr. */\n-\t\talready_mapped = 0;\n-\t\tfor (j = 0; j != pages_n; ++j) {\n-\t\t\tif (pages[j] == uar_va) {\n-\t\t\t\talready_mapped = 1;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t\t/* new address in reserved UAR address space. */\n-\t\taddr = RTE_PTR_ADD(mlx4_shared_data->uar_base,\n-\t\t\t\t   uar_va & (uintptr_t)(MLX4_UAR_SIZE - 1));\n-\t\tif (!already_mapped) {\n-\t\t\tpages[pages_n++] = uar_va;\n-\t\t\t/* fixed mmap to specified address in reserved\n-\t\t\t * address space.\n-\t\t\t */\n-\t\t\tret = mmap(addr, page_size,\n-\t\t\t\t   PROT_WRITE, MAP_FIXED | MAP_SHARED, fd,\n-\t\t\t\t   txq->msq.uar_mmap_offset);\n-\t\t\tif (ret != addr) {\n-\t\t\t\t/* fixed mmap has to return same address. */\n-\t\t\t\tERROR(\"port %u call to mmap failed on UAR\"\n-\t\t\t\t      \" for txq %u\",\n-\t\t\t\t      dev->data->port_id, i);\n-\t\t\t\trte_errno = ENXIO;\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\t\t}\n-\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY) /* save once. */\n-\t\t\ttxq->msq.db = RTE_PTR_ADD((void *)addr, off);\n-\t\telse\n-\t\t\tassert(txq->msq.db ==\n-\t\t\t       RTE_PTR_ADD((void *)addr, off));\n+\t\tassert(txq->stats.idx == (uint16_t)i);\n+\t\tret = txq_uar_init_secondary(txq, fd);\n+\t\tif (ret)\n+\t\t\tgoto error;\n \t}\n \treturn 0;\n+error:\n+\t/* Rollback. */\n+\tdo {\n+\t\ttxq = dev->data->tx_queues[i];\n+\t\tif (!txq)\n+\t\t\tcontinue;\n+\t\ttxq_uar_uninit_secondary(txq);\n+\t} while (i--);\n+\treturn -rte_errno;\n }\n #else\n int\n-mlx4_tx_uar_remap(struct rte_eth_dev *dev __rte_unused, int fd __rte_unused)\n+mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev __rte_unused,\n+\t\t\t   int fd __rte_unused)\n {\n-\t/*\n-\t * Even if rdma-core doesn't support UAR remap, primary process\n-\t * shouldn't be interrupted.\n-\t */\n-\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n-\t\treturn 0;\n+\tassert(rte_eal_process_type() == RTE_PROC_SECONDARY);\n \tERROR(\"UAR remap is not supported\");\n \trte_errno = ENOTSUP;\n \treturn -rte_errno;\n@@ -187,11 +224,10 @@ mlx4_txq_fill_dv_obj_info(struct txq *txq, struct mlx4dv_obj *mlxdv)\n \t\t\t\t     (0u << MLX4_SQ_OWNER_BIT));\n #ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET\n \tsq->uar_mmap_offset = dqp->uar_mmap_offset;\n-\tsq->qp_sdb = dqp->sdb;\n #else\n \tsq->uar_mmap_offset = -1; /* Make mmap() fail. */\n-\tsq->db = dqp->sdb;\n #endif\n+\tsq->db = dqp->sdb;\n \tsq->doorbell_qpn = dqp->doorbell_qpn;\n \tcq->buf = dcq->buf.buf;\n \tcq->cqe_cnt = dcq->cqe_cnt;\n@@ -314,6 +350,7 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,\n \t}\n \t*txq = (struct txq){\n \t\t.priv = priv,\n+\t\t.port_id = dev->data->port_id,\n \t\t.stats = {\n \t\t\t.idx = idx,\n \t\t},\n@@ -432,6 +469,7 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,\n \t}\n #endif\n \tmlx4_txq_fill_dv_obj_info(txq, &mlxdv);\n+\ttxq_uar_init(txq);\n \t/* Save first wqe pointer in the first element. */\n \t(&(*txq->elts)[0])->wqe =\n \t\t(volatile struct mlx4_wqe_ctrl_seg *)txq->msq.buf;\n",
    "prefixes": [
        "v4",
        "4/4"
    ]
}