1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
6 #include <rte_eal_memconfig.h>
7 #include <rte_mempool.h>
8 #include <rte_malloc.h>
9 #include <rte_rwlock.h>
11 #include <mlx5_common_mp.h>
12 #include <mlx5_common_mr.h>
15 #include "mlx5_rxtx.h"
20 * Bottom-half of LKey search on Tx.
23 * Pointer to Tx queue structure.
28 * Searched LKey on success, UINT32_MAX on no match.
31 mlx5_tx_addr2mr_bh(struct mlx5_txq_data *txq, uintptr_t addr)
33 struct mlx5_txq_ctrl *txq_ctrl =
34 container_of(txq, struct mlx5_txq_ctrl, txq);
35 struct mlx5_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
36 struct mlx5_priv *priv = txq_ctrl->priv;
38 return mlx5_mr_addr2mr_bh(priv->sh->cdev->pd, &priv->mp_id,
39 &priv->sh->cdev->mr_scache, mr_ctrl, addr,
40 priv->sh->cdev->config.mr_ext_memseg_en);
44 * Bottom-half of LKey search on Tx. If it can't be searched in the memseg
45 * list, register the mempool of the mbuf as externally allocated memory.
48 * Pointer to Tx queue structure.
53 * Searched LKey on success, UINT32_MAX on no match.
56 mlx5_tx_mb2mr_bh(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
58 struct mlx5_txq_ctrl *txq_ctrl =
59 container_of(txq, struct mlx5_txq_ctrl, txq);
60 struct mlx5_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
61 struct mlx5_priv *priv = txq_ctrl->priv;
62 uintptr_t addr = (uintptr_t)mb->buf_addr;
65 if (priv->sh->cdev->config.mr_mempool_reg_en) {
66 struct rte_mempool *mp = NULL;
67 struct mlx5_mprq_buf *buf;
69 if (!RTE_MBUF_HAS_EXTBUF(mb)) {
71 } else if (mb->shinfo->free_cb == mlx5_mprq_buf_free_cb) {
72 /* Recover MPRQ mempool. */
73 buf = mb->shinfo->fcb_opaque;
77 lkey = mlx5_mr_mempool2mr_bh(&priv->sh->cdev->mr_scache,
80 * Lookup can only fail on invalid input, e.g. "addr"
81 * is not from "mp" or "mp" has RTE_MEMPOOL_F_NON_IO set.
83 if (lkey != UINT32_MAX)
86 /* Fallback for generic mechanism in corner cases. */
88 return mlx5_tx_addr2mr_bh(txq, addr);
92 * Finds the first ethdev that match the device.
93 * The existence of multiple ethdev per pci device is only with representors.
94 * On such case, it is enough to get only one of the ports as they all share
95 * the same ibv context.
98 * Pointer to the device.
101 * Pointer to the ethdev if found, NULL otherwise.
103 static struct rte_eth_dev *
104 dev_to_eth_dev(struct rte_device *dev)
108 port_id = rte_eth_find_next_of(0, dev);
109 if (port_id == RTE_MAX_ETHPORTS)
111 return &rte_eth_devices[port_id];
115 * Callback to DMA map external memory to a device.
118 * Pointer to the generic device.
120 * Starting virtual address of memory to be mapped.
122 * Starting IOVA address of memory to be mapped.
124 * Length of memory segment being mapped.
127 * 0 on success, negative value on error.
130 mlx5_net_dma_map(struct rte_device *rte_dev, void *addr,
131 uint64_t iova __rte_unused, size_t len)
133 struct rte_eth_dev *dev;
135 struct mlx5_priv *priv;
136 struct mlx5_common_device *cdev;
138 dev = dev_to_eth_dev(rte_dev);
140 DRV_LOG(WARNING, "unable to find matching ethdev "
141 "to device %s", rte_dev->name);
145 priv = dev->data->dev_private;
146 cdev = priv->sh->cdev;
147 mr = mlx5_create_mr_ext(cdev->pd, (uintptr_t)addr, len,
148 SOCKET_ID_ANY, cdev->mr_scache.reg_mr_cb);
151 "port %u unable to dma map", dev->data->port_id);
155 rte_rwlock_write_lock(&cdev->mr_scache.rwlock);
156 LIST_INSERT_HEAD(&cdev->mr_scache.mr_list, mr, mr);
157 /* Insert to the global cache table. */
158 mlx5_mr_insert_cache(&cdev->mr_scache, mr);
159 rte_rwlock_write_unlock(&cdev->mr_scache.rwlock);
164 * Callback to DMA unmap external memory to a device.
167 * Pointer to the generic device.
169 * Starting virtual address of memory to be unmapped.
171 * Starting IOVA address of memory to be unmapped.
173 * Length of memory segment being unmapped.
176 * 0 on success, negative value on error.
179 mlx5_net_dma_unmap(struct rte_device *rte_dev, void *addr,
180 uint64_t iova __rte_unused, size_t len __rte_unused)
182 struct rte_eth_dev *dev;
183 struct mlx5_priv *priv;
184 struct mlx5_common_device *cdev;
186 struct mr_cache_entry entry;
188 dev = dev_to_eth_dev(rte_dev);
190 DRV_LOG(WARNING, "unable to find matching ethdev to device %s",
195 priv = dev->data->dev_private;
196 cdev = priv->sh->cdev;
197 rte_rwlock_write_lock(&cdev->mr_scache.rwlock);
198 mr = mlx5_mr_lookup_list(&cdev->mr_scache, &entry, (uintptr_t)addr);
200 rte_rwlock_write_unlock(&cdev->mr_scache.rwlock);
201 DRV_LOG(WARNING, "address 0x%" PRIxPTR " wasn't registered to device %s",
202 (uintptr_t)addr, rte_dev->name);
207 DRV_LOG(DEBUG, "port %u remove MR(%p) from list", dev->data->port_id,
209 mlx5_mr_free(mr, cdev->mr_scache.dereg_mr_cb);
210 mlx5_mr_rebuild_cache(&cdev->mr_scache);
212 * No explicit wmb is needed after updating dev_gen due to
213 * store-release ordering in unlock that provides the
214 * implicit barrier at the software visible level.
216 ++cdev->mr_scache.dev_gen;
217 DRV_LOG(DEBUG, "broadcasting local cache flush, gen=%d",
218 cdev->mr_scache.dev_gen);
219 rte_rwlock_write_unlock(&cdev->mr_scache.rwlock);