shenango-bsd/mlx.patch

233 lines
8.0 KiB
Diff

From cbc5e1d4d611dfb24ed1f444ed5a2acad1aaded2 Mon Sep 17 00:00:00 2001
From: Amy Ousterhout <aousterh@mit.edu>
Date: Wed, 28 Feb 2018 20:12:41 -0500
Subject: [PATCH] enable mlx4 tx memory registration using explicit start and
end addrs specified in mbufs, instead of inferring these from mempools
Detect/handle reuse of shared memory virtual addresses
---
drivers/net/mlx4/mlx4.h | 10 ++++++-
drivers/net/mlx4/mlx4_mr.c | 70 ++++++++++++++++++++++++++++++++++++++++++--
drivers/net/mlx4/mlx4_rxq.c | 2 +-
drivers/net/mlx4/mlx4_rxtx.c | 2 +-
drivers/net/mlx4/mlx4_rxtx.h | 46 +++++++++++++++++++++++++++++
5 files changed, 124 insertions(+), 6 deletions(-)
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 19c8a223d..869610981 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -156,9 +156,17 @@ int mlx4_rx_intr_enable(struct rte_eth_dev *dev, uint16_t idx);
/* mlx4_mr.c */
-struct mlx4_mr *mlx4_mr_get(struct priv *priv, struct rte_mempool *mp);
+struct mem_info {
+ uintptr_t uniqid;
+ uintptr_t start_addr;
+ uintptr_t end_addr;
+};
+
+struct mlx4_mr *mlx4_mr_get(struct priv *priv, struct rte_mempool *mp, struct mem_info *m);
void mlx4_mr_put(struct mlx4_mr *mr);
uint32_t mlx4_txq_add_mr(struct txq *txq, struct rte_mempool *mp,
uint32_t i);
+uint32_t mlx4_txq_add_mr_from_mem_info(struct txq *txq, struct mem_info *m,
+ uint32_t i);
#endif /* RTE_PMD_MLX4_H_ */
diff --git a/drivers/net/mlx4/mlx4_mr.c b/drivers/net/mlx4/mlx4_mr.c
index 9a1e4de3d..d2e2462c6 100644
--- a/drivers/net/mlx4/mlx4_mr.c
+++ b/drivers/net/mlx4/mlx4_mr.c
@@ -120,11 +120,14 @@ mlx4_check_mempool(struct rte_mempool *mp, uintptr_t *start, uintptr_t *end)
* @param mp
* Pointer to memory pool.
*
+ * @param m
+ * Auxiliary info about memory region - use this instead of mempool if non-NULL
+ *
* @return
* Memory region pointer, NULL in case of error and rte_errno is set.
*/
struct mlx4_mr *
-mlx4_mr_get(struct priv *priv, struct rte_mempool *mp)
+mlx4_mr_get(struct priv *priv, struct rte_mempool *mp, struct mem_info *m)
{
const struct rte_memseg *ms = rte_eal_get_physmem_layout();
uintptr_t start;
@@ -132,7 +135,15 @@ mlx4_mr_get(struct priv *priv, struct rte_mempool *mp)
unsigned int i;
struct mlx4_mr *mr;
- if (mlx4_check_mempool(mp, &start, &end) != 0) {
+ if (m != NULL) {
+ start = m->start_addr;
+ end = m->end_addr;
+
+ /* this is really ugly, but the pointer to the mempool is used
+ * only as an identifier... we use the memory region start addr
+ * instead.*/
+ mp = (struct rte_mempool *) m->start_addr;
+ } else if (mlx4_check_mempool(mp, &start, &end) != 0) {
rte_errno = EINVAL;
ERROR("mempool %p: not virtually contiguous",
(void *)mp);
@@ -241,7 +252,7 @@ mlx4_txq_add_mr(struct txq *txq, struct rte_mempool *mp, uint32_t i)
/* Add a new entry, register MR first. */
DEBUG("%p: discovered new memory pool \"%s\" (%p)",
(void *)txq, mp->name, (void *)mp);
- mr = mlx4_mr_get(txq->priv, mp);
+ mr = mlx4_mr_get(txq->priv, mp, NULL);
if (unlikely(mr == NULL)) {
DEBUG("%p: unable to configure MR, mlx4_mr_get() failed",
(void *)txq);
@@ -264,3 +275,56 @@ mlx4_txq_add_mr(struct txq *txq, struct rte_mempool *mp, uint32_t i)
(void *)txq, mp->name, (void *)mp, txq->mp2mr[i].lkey);
return txq->mp2mr[i].lkey;
}
+
+
+/**
+ * Add memory region (MR) <-> memory id association to txq->id2mr[].
+ * If id2mr[] is full, remove an entry first.
+ *
+ * @param txq
+ * Pointer to Tx queue structure.
+ * @param[in] mem_info
+ * Info about region for which a memory region lkey must be added.
+ * @param[in] i
+ * Index in memory pool (MP) where to add memory region (MR).
+ *
+ * @return
+ * Added mr->lkey on success, (uint32_t)-1 on failure.
+ */
+uint32_t
+mlx4_txq_add_mr_from_mem_info(struct txq *txq, struct mem_info *m, uint32_t i)
+{
+ struct mlx4_mr *mr;
+
+ if (i != RTE_DIM(txq->mp2mr) && txq->id2mr[i].id != 0) {
+ /* Need to replace an existing entry. */
+ DEBUG("%p: replacing possibly stale MR", (void *)txq);
+ mlx4_mr_put(txq->id2mr[i].mr); // Hopefully refcnt is 1
+ }
+
+ /* Add a new entry, register MR first. */
+ DEBUG("%p: discovered new mem info", (void *)txq);
+ mr = mlx4_mr_get(txq->priv, NULL, m);
+ if (unlikely(mr == NULL)) {
+ DEBUG("%p: unable to configure MR, mlx4_mr_get() failed",
+ (void *)txq);
+ return (uint32_t)-1;
+ }
+ if (unlikely(i == RTE_DIM(txq->id2mr))) {
+ /* Table is full, remove oldest entry. */
+ DEBUG("%p: MR <-> ID table full, dropping oldest entry.",
+ (void *)txq);
+ --i;
+ mlx4_mr_put(txq->id2mr[0].mr);
+ memmove(&txq->id2mr[0], &txq->id2mr[1],
+ (sizeof(txq->id2mr) - sizeof(txq->id2mr[0])));
+ }
+ /* Store the new entry. */
+ txq->id2mr[i].id = m->uniqid;
+ txq->id2mr[i].mr = mr;
+ txq->id2mr[i].lkey = mr->lkey;
+ DEBUG("%p: new MR lkey for mem_info %p %p: 0x%08" PRIu32,
+ (void *)txq, (void *) m->start_addr, (void *) m->end_addr,
+ txq->id2mr[i].lkey);
+ return txq->id2mr[i].lkey;
+}
diff --git a/drivers/net/mlx4/mlx4_rxq.c b/drivers/net/mlx4/mlx4_rxq.c
index 7a036ed83..f80c70616 100644
--- a/drivers/net/mlx4/mlx4_rxq.c
+++ b/drivers/net/mlx4/mlx4_rxq.c
@@ -848,7 +848,7 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
goto error;
}
/* Use the entire Rx mempool as the memory region. */
- rxq->mr = mlx4_mr_get(priv, mp);
+ rxq->mr = mlx4_mr_get(priv, mp, NULL);
if (!rxq->mr) {
ERROR("%p: MR creation failure: %s",
(void *)dev, strerror(rte_errno));
diff --git a/drivers/net/mlx4/mlx4_rxtx.c b/drivers/net/mlx4/mlx4_rxtx.c
index 8ca8b77cc..ae86d5f90 100644
--- a/drivers/net/mlx4/mlx4_rxtx.c
+++ b/drivers/net/mlx4/mlx4_rxtx.c
@@ -611,7 +611,7 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
elt->buf = NULL;
break;
}
- lkey = mlx4_txq_mp2mr(txq, mlx4_txq_mb2mp(buf));
+ lkey = mlx4_txq_buf2mr(txq, buf);
if (unlikely(lkey == (uint32_t)-1)) {
/* MR does not exist. */
DEBUG("%p: unable to get MP <-> MR association",
diff --git a/drivers/net/mlx4/mlx4_rxtx.h b/drivers/net/mlx4/mlx4_rxtx.h
index c12bd39a9..e7645e932 100644
--- a/drivers/net/mlx4/mlx4_rxtx.h
+++ b/drivers/net/mlx4/mlx4_rxtx.h
@@ -113,6 +113,11 @@ struct txq {
struct mlx4_mr *mr; /**< Memory region (for mp). */
uint32_t lkey; /**< mr->lkey copy. */
} mp2mr[MLX4_PMD_TX_MP_CACHE]; /**< MP to MR translation table. */
+ struct {
+ uintptr_t id; /**< id of mem region (proc->uniqid). */
+ struct mlx4_mr *mr; /**< Memory region. */
+ uint32_t lkey; /**< mr->lkey copy. */
+ } id2mr[MLX4_PMD_TX_MP_CACHE]; /**< id to MR translation table. */
struct priv *priv; /**< Back pointer to private data. */
unsigned int socket; /**< CPU socket ID for allocations. */
struct ibv_cq *cq; /**< Completion queue. */
@@ -190,4 +195,45 @@ mlx4_txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
return mlx4_txq_add_mr(txq, mp, i);
}
+#define __max(x,y) ((x) > (y) ? (x) : (y))
+#define __min(x,y) ((x) < (y) ? (x) : (y))
+/**
+ * Get memory region (MR) <-> buffer association from txq->id2mr[].
+ * Call mlx4_txq_add_mr() if buffer's memory region is not registered yet.
+ *
+ * @param txq
+ * Pointer to Tx queue structure.
+ * @param[in] buf
+ * Buffer for which a memory region lkey must be returned.
+ *
+ * @return
+ * mr->lkey on success, (uint32_t)-1 on failure.
+ */
+static inline uint32_t
+mlx4_txq_buf2mr(struct txq *txq, struct rte_mbuf *buf)
+{
+ unsigned int i;
+ struct mem_info *m = (struct mem_info *)(((char *)buf) +
+ sizeof(struct rte_mbuf));
+
+ for (i = 0; (i != RTE_DIM(txq->id2mr)); ++i) {
+ if (unlikely(txq->id2mr[i].id == 0)) {
+ /* Unknown region, add a new MR for it. */
+ break;
+ }
+ if (txq->id2mr[i].id == m->uniqid) {
+ /* Found region. */
+ return txq->id2mr[i].lkey;
+ }
+ if (__max(txq->id2mr[i].mr->start, m->start_addr) <
+ __min(txq->id2mr[i].mr->end, m->end_addr)) {
+ /* Recreate lkey/mr for previously mapped regions */
+ return mlx4_txq_add_mr_from_mem_info(txq, m, i);
+ }
+ }
+ return mlx4_txq_add_mr_from_mem_info(txq, m, i);
+}
+
+#undef __max
+#undef __min
#endif /* MLX4_RXTX_H_ */
--
2.14.1