]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx4: add external allocator for Verbs object
authorYongseok Koh <yskoh@mellanox.com>
Mon, 1 Apr 2019 21:15:52 +0000 (14:15 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 5 Apr 2019 15:45:22 +0000 (17:45 +0200)
To support secondary process, the memory allocated by library such as
completion rings (CQ) and buffer rings (WQ) must be manageable by EAL,
in order to share it with secondary processes. With new changes in
rdma-core and kernel driver, it is possible to provide an external
allocator to the library layer for this purpose. All such resources
will now be allocated within DPDK framework.

Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
Acked-by: Shahaf Shuler <shahafs@mellanox.com>
drivers/net/mlx4/Makefile
drivers/net/mlx4/meson.build
drivers/net/mlx4/mlx4.c
drivers/net/mlx4/mlx4.h
drivers/net/mlx4/mlx4_rxq.c
drivers/net/mlx4/mlx4_txq.c

index 1f1b9274849e251b5e14a00d6cc1b30617110f96..b527efd6259e591e9162e6cbc621bbe888225df4 100644 (file)
@@ -87,6 +87,11 @@ mlx4_autoconf.h.new: FORCE
 mlx4_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
        $Q $(RM) -f -- '$@'
        $Q : > '$@'
+       $Q sh -- '$<' '$@' \
+               HAVE_IBV_MLX4_BUF_ALLOCATORS \
+               infiniband/mlx4dv.h \
+               enum MLX4DV_SET_CTX_ATTR_BUF_ALLOCATORS \
+               $(AUTOCONF_OUTPUT)
        $Q sh -- '$<' '$@' \
                HAVE_IBV_MLX4_WQE_LSO_SEG \
                infiniband/mlx4dv.h \
index b4f9672e737a1a940a5732eeac5d88501ec39902..650e2c8fbcc9c62908f60ad379f16abab933aff2 100644 (file)
@@ -70,7 +70,17 @@ if build
                [ 'HAVE_IBV_MLX4_WQE_LSO_SEG', 'infiniband/mlx4dv.h',
                'struct mlx4_wqe_lso_seg', 'mss_hdr_size' ],
        ]
+       # input array for meson symbol search:
+       # [ "MACRO to define if found", "header for the search",
+       #   "symbol to search" ]
+       has_sym_args = [
+               [ 'HAVE_IBV_MLX4_BUF_ALLOCATORS', 'infiniband/mlx4dv.h',
+               'MLX4DV_SET_CTX_ATTR_BUF_ALLOCATORS' ],
+       ]
        config = configuration_data()
+       foreach arg:has_sym_args
+               config.set(arg[0], cc.has_header_symbol(arg[1], arg[2]))
+       endforeach
        foreach arg:has_member_args
                file_prefix = '#include<' + arg[1] + '>'
                config.set(arg[0], cc.has_member(arg[2], arg[3],
index bb6ab8ec6ec3cbf2ec20d7fa6631bdffcbcb1be5..0e0b035df01b345b77422e40758278194cdb305a 100644 (file)
@@ -69,6 +69,62 @@ const char *pmd_mlx4_init_params[] = {
 
 static void mlx4_dev_stop(struct rte_eth_dev *dev);
 
+#ifdef HAVE_IBV_MLX4_BUF_ALLOCATORS
+/**
+ * Verbs callback to allocate a memory. This function should allocate the space
+ * according to the size provided residing inside a huge page.
+ * Please note that all allocation must respect the alignment from libmlx4
+ * (i.e. currently sysconf(_SC_PAGESIZE)).
+ *
+ * @param[in] size
+ *   The size in bytes of the memory to allocate.
+ * @param[in] data
+ *   A pointer to the callback data.
+ *
+ * @return
+ *   Allocated buffer, NULL otherwise and rte_errno is set.
+ */
+static void *
+mlx4_alloc_verbs_buf(size_t size, void *data)
+{
+       struct mlx4_priv *priv = data;
+       void *ret;
+       size_t alignment = sysconf(_SC_PAGESIZE);
+       unsigned int socket = SOCKET_ID_ANY;
+
+       if (priv->verbs_alloc_ctx.type == MLX4_VERBS_ALLOC_TYPE_TX_QUEUE) {
+               const struct txq *txq = priv->verbs_alloc_ctx.obj;
+
+               socket = txq->socket;
+       } else if (priv->verbs_alloc_ctx.type ==
+                  MLX4_VERBS_ALLOC_TYPE_RX_QUEUE) {
+               const struct rxq *rxq = priv->verbs_alloc_ctx.obj;
+
+               socket = rxq->socket;
+       }
+       assert(data != NULL);
+       ret = rte_malloc_socket(__func__, size, alignment, socket);
+       if (!ret && size)
+               rte_errno = ENOMEM;
+       return ret;
+}
+
+/**
+ * Verbs callback to free a memory.
+ *
+ * @param[in] ptr
+ *   A pointer to the memory to free.
+ * @param[in] data
+ *   A pointer to the callback data.
+ */
+static void
+mlx4_free_verbs_buf(void *ptr, void *data __rte_unused)
+{
+       assert(data != NULL);
+       rte_free(ptr);
+}
+#endif
+
 /**
  * DPDK callback for Ethernet device configuration.
  *
@@ -755,6 +811,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                eth_dev->intr_handle = &priv->intr_handle;
                priv->dev_data = eth_dev->data;
                eth_dev->dev_ops = &mlx4_dev_ops;
+#ifdef HAVE_IBV_MLX4_BUF_ALLOCATORS
+               /* Hint libmlx4 to use PMD allocator for data plane resources */
+               struct mlx4dv_ctx_allocators alctr = {
+                       .alloc = &mlx4_alloc_verbs_buf,
+                       .free = &mlx4_free_verbs_buf,
+                       .data = priv,
+               };
+               mlx4_glue->dv_set_context_attr
+                       (ctx, MLX4DV_SET_CTX_ATTR_BUF_ALLOCATORS,
+                        (void *)((uintptr_t)&alctr));
+#endif
                /* Bring Ethernet device up. */
                DEBUG("forcing Ethernet interface up");
                mlx4_dev_set_link_up(eth_dev);
index 51566caf7f9295ef231a081ccfd6531404ef415f..d43e05ea740aad6525b9ebe112a79241e3d0f464 100644 (file)
@@ -72,6 +72,24 @@ struct rxq;
 struct txq;
 struct rte_flow;
 
+/**
+ * Type of objet being allocated.
+ */
+enum mlx4_verbs_alloc_type {
+       MLX4_VERBS_ALLOC_TYPE_NONE,
+       MLX4_VERBS_ALLOC_TYPE_TX_QUEUE,
+       MLX4_VERBS_ALLOC_TYPE_RX_QUEUE,
+};
+
+/**
+ * Verbs allocator needs a context to know in the callback which kind of
+ * resources it is allocating.
+ */
+struct mlx4_verbs_alloc_ctx {
+       enum mlx4_verbs_alloc_type type; /* Kind of object being allocated. */
+       const void *obj; /* Pointer to the DPDK object. */
+};
+
 LIST_HEAD(mlx4_dev_list, mlx4_priv);
 LIST_HEAD(mlx4_mr_list, mlx4_mr);
 
@@ -111,6 +129,8 @@ struct mlx4_priv {
        LIST_HEAD(, rte_flow) flows; /**< Configured flow rule handles. */
        struct ether_addr mac[MLX4_MAX_MAC_ADDRESSES];
        /**< Configured MAC addresses. Unused entries are zeroed. */
+       struct mlx4_verbs_alloc_ctx verbs_alloc_ctx;
+       /**< Context for Verbs allocator. */
 };
 
 #define PORT_ID(priv) ((priv)->dev_data->port_id)
index 50f33eb0c5e3b83449347d19b8b1f86dda307551..f45c1ff85c4d40638ae00d88cea65324c981c1aa 100644 (file)
@@ -513,6 +513,8 @@ mlx4_rxq_attach(struct rxq *rxq)
        int ret;
 
        assert(rte_is_power_of_2(elts_n));
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_RX_QUEUE;
+       priv->verbs_alloc_ctx.obj = rxq;
        cq = mlx4_glue->create_cq(priv->ctx, elts_n / sges_n, NULL,
                                  rxq->channel, 0);
        if (!cq) {
@@ -620,6 +622,7 @@ mlx4_rxq_attach(struct rxq *rxq)
        rxq->rq_ci = elts_n / sges_n;
        rte_wmb();
        *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_NONE;
        return 0;
 error:
        if (wq)
@@ -630,6 +633,7 @@ error:
        rte_errno = ret;
        ERROR("error while attaching Rx queue %p: %s: %s",
              (void *)rxq, msg, strerror(ret));
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_NONE;
        return -ret;
 }
 
index 352700820dd679ab834c30c31a5c5a0fe977864a..2dc198e77fbb6c0a225b24aaafb48a9e3b54eb69 100644 (file)
@@ -177,10 +177,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        uint64_t offloads;
 
        offloads = conf->offloads | dev->data->dev_conf.txmode.offloads;
-
        DEBUG("%p: configuring queue %u for %u descriptors",
              (void *)dev, idx, desc);
-
        if (idx >= dev->data->nb_tx_queues) {
                rte_errno = EOVERFLOW;
                ERROR("%p: queue index out of range (%u >= %u)",
@@ -241,6 +239,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
                .lb = !!priv->vf,
                .bounce_buf = bounce_buf,
        };
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_TX_QUEUE;
+       priv->verbs_alloc_ctx.obj = txq;
        txq->cq = mlx4_glue->create_cq(priv->ctx, desc, NULL, NULL, 0);
        if (!txq->cq) {
                rte_errno = ENOMEM;
@@ -331,6 +331,7 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        txq->mr_ctrl.dev_gen_ptr = &priv->mr.dev_gen;
        DEBUG("%p: adding Tx queue %p to list", (void *)dev, (void *)txq);
        dev->data->tx_queues[idx] = txq;
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_NONE;
        return 0;
 error:
        dev->data->tx_queues[idx] = NULL;
@@ -338,6 +339,7 @@ error:
        mlx4_tx_queue_release(txq);
        rte_errno = ret;
        assert(rte_errno > 0);
+       priv->verbs_alloc_ctx.type = MLX4_VERBS_ALLOC_TYPE_NONE;
        return -rte_errno;
 }