summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/mlx5/mlx5.c119
-rw-r--r--drivers/net/mlx5/mlx5.h21
-rw-r--r--drivers/net/mlx5/mlx5_glue.h2
-rw-r--r--drivers/net/mlx5/mlx5_rxtx.h1
4 files changed, 142 insertions, 1 deletions
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index fca2dbf..8c1bd32 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1312,6 +1312,125 @@ exit:
}
/**
+ * Allocate page of door-bells and register it using DevX API.
+ *
+ * @param [in] dev
+ * Pointer to Ethernet device.
+ *
+ * @return
+ * Pointer to new page on success, NULL otherwise.
+ */
+static struct mlx5_devx_dbr_page *
+mlx5_alloc_dbr_page(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_dbr_page *page;
+
+ /* Allocate space for door-bell page and management data. */
+ page = rte_calloc_socket(__func__, 1, sizeof(struct mlx5_devx_dbr_page),
+ RTE_CACHE_LINE_SIZE, dev->device->numa_node);
+ if (!page) {
+ DRV_LOG(ERR, "port %u cannot allocate dbr page",
+ dev->data->port_id);
+ return NULL;
+ }
+ /* Register allocated memory. */
+ page->umem = mlx5_glue->devx_umem_reg(priv->sh->ctx, page->dbrs,
+ MLX5_DBR_PAGE_SIZE, 0);
+ if (!page->umem) {
+ DRV_LOG(ERR, "port %u cannot umem reg dbr page",
+ dev->data->port_id);
+ rte_free(page);
+ return NULL;
+ }
+ return page;
+}
+
+/**
+ * Find the next available door-bell, allocate new page if needed.
+ *
+ * @param [in] dev
+ * Pointer to Ethernet device.
+ * @param [out] dbr_page
+ * Door-bell page containing the page data.
+ *
+ * @return
+ * Door-bell address offset on success, a negative error value otherwise.
+ */
+int64_t
+mlx5_get_dbr(struct rte_eth_dev *dev, struct mlx5_devx_dbr_page **dbr_page)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_dbr_page *page = NULL;
+ uint32_t i, j;
+
+ LIST_FOREACH(page, &priv->dbrpgs, next)
+ if (page->dbr_count < MLX5_DBR_PER_PAGE)
+ break;
+ if (!page) { /* No page with free door-bell exists. */
+ page = mlx5_alloc_dbr_page(dev);
+ if (!page) /* Failed to allocate new page. */
+ return (-1);
+ LIST_INSERT_HEAD(&priv->dbrpgs, page, next);
+ }
+ /* Loop to find bitmap part with clear bit. */
+ for (i = 0;
+ i < MLX5_DBR_BITMAP_SIZE && page->dbr_bitmap[i] == UINT64_MAX;
+ i++)
+ ; /* Empty. */
+ /* Find the first clear bit. */
+ j = rte_bsf64(~page->dbr_bitmap[i]);
+ assert(i < (MLX5_DBR_PER_PAGE / 64));
+ page->dbr_bitmap[i] |= (1 << j);
+ page->dbr_count++;
+ *dbr_page = page;
+ return (((i * 64) + j) * sizeof(uint64_t));
+}
+
+/**
+ * Release a door-bell record.
+ *
+ * @param [in] dev
+ * Pointer to Ethernet device.
+ * @param [in] umem_id
+ * UMEM ID of page containing the door-bell record to release.
+ * @param [in] offset
+ * Offset of door-bell record in page.
+ *
+ * @return
+ * 0 on success, a negative error value otherwise.
+ */
+int32_t
+mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id, uint64_t offset)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_devx_dbr_page *page = NULL;
+ int ret = 0;
+
+ LIST_FOREACH(page, &priv->dbrpgs, next)
+ /* Find the page this address belongs to. */
+ if (page->umem->umem_id == umem_id)
+ break;
+ if (!page)
+ return -EINVAL;
+ page->dbr_count--;
+ if (!page->dbr_count) {
+ /* Page not used, free it and remove from list. */
+ LIST_REMOVE(page, next);
+ if (page->umem)
+ ret = -mlx5_glue->devx_umem_dereg(page->umem);
+ rte_free(page);
+ } else {
+ /* Mark in bitmap that this door-bell is not in use. */
+ int i = offset / 64;
+ int j = offset % 64;
+
+ page->dbr_bitmap[i] &= ~(1 << j);
+ }
+ return ret;
+}
+
+/**
* Spawn an Ethernet device from Verbs information.
*
* @param dpdk_dev
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 8aa5240..92daf86 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -36,6 +36,7 @@
#include "mlx5_mr.h"
#include "mlx5_autoconf.h"
#include "mlx5_defs.h"
+#include "mlx5_glue.h"
enum {
PCI_VENDOR_ID_MELLANOX = 0x15b3,
@@ -498,6 +499,21 @@ struct mlx5_flow_tbl_resource {
#define MLX5_MAX_TABLES_FDB 32
#define MLX5_GROUP_FACTOR 1
+#define MLX5_DBR_PAGE_SIZE 4096 /* Must be >= 512. */
+#define MLX5_DBR_SIZE 8
+#define MLX5_DBR_PER_PAGE (MLX5_DBR_PAGE_SIZE / MLX5_DBR_SIZE)
+#define MLX5_DBR_BITMAP_SIZE (MLX5_DBR_PER_PAGE / 64)
+
+struct mlx5_devx_dbr_page {
+ /* Door-bell records, must be first member in structure. */
+ uint8_t dbrs[MLX5_DBR_PAGE_SIZE];
+ LIST_ENTRY(mlx5_devx_dbr_page) next; /* Pointer to the next element. */
+ struct mlx5dv_devx_umem *umem;
+ uint32_t dbr_count; /* Number of door-bell records in use. */
+ /* 1 bit marks matching door-bell is in use. */
+ uint64_t dbr_bitmap[MLX5_DBR_BITMAP_SIZE];
+};
+
/*
* Shared Infiniband device context for Master/Representors
* which belong to same IB device with multiple IB ports.
@@ -618,6 +634,7 @@ struct mlx5_priv {
int nl_socket_rdma; /* Netlink socket (NETLINK_RDMA). */
int nl_socket_route; /* Netlink socket (NETLINK_ROUTE). */
uint32_t nl_sn; /* Netlink message sequence number. */
+ LIST_HEAD(dbrpage, mlx5_devx_dbr_page) dbrpgs; /* Door-bell pages. */
#ifndef RTE_ARCH_64
rte_spinlock_t uar_lock_cq; /* CQs share a common distinct UAR */
rte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];
@@ -632,6 +649,10 @@ struct mlx5_priv {
int mlx5_getenv_int(const char *);
int mlx5_proc_priv_init(struct rte_eth_dev *dev);
+int64_t mlx5_get_dbr(struct rte_eth_dev *dev,
+ struct mlx5_devx_dbr_page **dbr_page);
+int32_t mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id,
+ uint64_t offset);
/* mlx5_ethdev.c */
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f8e2b9a..6b5dadf 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -61,7 +61,7 @@ enum mlx5dv_flow_table_type { flow_table_type = 0, };
#ifndef HAVE_IBV_DEVX_OBJ
struct mlx5dv_devx_obj;
-struct mlx5dv_devx_umem;
+struct mlx5dv_devx_umem { uint32_t umem_id; };
#endif
#ifndef HAVE_IBV_DEVX_ASYNC
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 2f688ac..436b453 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -29,6 +29,7 @@
#include <rte_spinlock.h>
#include <rte_io.h>
#include <rte_bus_pci.h>
+#include <rte_malloc.h>
#include "mlx5_utils.h"
#include "mlx5.h"