From: "Nélio Laranjeiro" <nelio.laranjeiro@6wind.com>
To: Xueming Li <xuemingl@mellanox.com>
Cc: Shahaf Shuler <shahafs@mellanox.com>, dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH 3/4] net/mlx5: support mempool of multi-mem segments
Date: Mon, 15 Jan 2018 17:29:46 +0100 [thread overview]
Message-ID: <20180115162946.hu7mtcruyb66ke7d@shalom> (raw)
In-Reply-To: <20180115065420.44065-3-xuemingl@mellanox.com>
Hi Xueming,
On Mon, Jan 15, 2018 at 02:54:19PM +0800, Xueming Li wrote:
> Previously, mempool of multiple memory segments would lead to MR
> registration error "mempool not virtually contiguous". This patch
> support multi-segments mempool by registering each memory segment of
> mempool.
>
> Signed-off-by: Xueming Li <xuemingl@mellanox.com>
> ---
> drivers/net/mlx5/mlx5.h | 4 +-
> drivers/net/mlx5/mlx5_mr.c | 284 ++++++++++++++--------------------------
> drivers/net/mlx5/mlx5_rxq.c | 29 ++--
> drivers/net/mlx5/mlx5_rxtx.h | 48 ++++---
> drivers/net/mlx5/mlx5_trigger.c | 7 -
> 5 files changed, 143 insertions(+), 229 deletions(-)
>
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> index 8ee522069..a6cd1474c 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -316,9 +316,11 @@ int priv_socket_connect(struct priv *priv);
>
> /* mlx5_mr.c */
>
> -struct mlx5_mr *priv_mr_new(struct priv *, struct rte_mempool *);
> +struct mlx5_mr *priv_mr_new(struct priv *priv, struct rte_mempool *mp,
> + uintptr_t addr);
> struct mlx5_mr *priv_mr_get(struct priv *, struct rte_mempool *);
> int priv_mr_release(struct priv *, struct mlx5_mr *);
> int priv_mr_verify(struct priv *);
> +struct mlx5_mr *priv_mr_lookup(struct priv *priv, uintptr_t addr);
>
> #endif /* RTE_PMD_MLX5_H_ */
> diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c
> index 3c80fbb89..8d8fabea1 100644
> --- a/drivers/net/mlx5/mlx5_mr.c
> +++ b/drivers/net/mlx5/mlx5_mr.c
> @@ -47,158 +47,89 @@
> #include "mlx5.h"
> #include "mlx5_rxtx.h"
>
> -struct mlx5_check_mempool_data {
> - int ret;
> - char *start;
> - char *end;
> +struct mlx5_mempool_cb_data {
> + uintptr_t addr;
> + struct priv *priv;
> + int error;
> + struct mlx5_mr *mr;
> };
>
> -/* Called by mlx5_check_mempool() when iterating the memory chunks. */
> +/* Called by priv_mr_new() when iterating the memory chunks. */
> static void
> -mlx5_check_mempool_cb(struct rte_mempool *mp,
> - void *opaque, struct rte_mempool_memhdr *memhdr,
> - unsigned int mem_idx)
> +mlx5_mempool_register_cb(struct rte_mempool *mp, void *opaque,
> + struct rte_mempool_memhdr *memhdr,
> + unsigned int mem_idx __rte_unused)
> {
> - struct mlx5_check_mempool_data *data = opaque;
> -
> - (void)mp;
> - (void)mem_idx;
> + struct mlx5_mempool_cb_data *cb = opaque;
> + struct priv *priv = cb->priv;
> + struct mlx5_mr *mr;
>
> - /* It already failed, skip the next chunks. */
> - if (data->ret != 0)
> + if (cb->error) /* skip on previous error */
> return;
> - /* It is the first chunk. */
> - if (data->start == NULL && data->end == NULL) {
> - data->start = memhdr->addr;
> - data->end = data->start + memhdr->len;
> + if (cb->addr && (cb->addr < (uintptr_t)memhdr->addr ||
> + cb->addr > (uintptr_t)memhdr->addr + memhdr->len))
> + return; /* not target mem segment */
> + mr = priv_mr_lookup(priv, (uintptr_t)memhdr->addr);
> + if (mr) { /* memory already registered */
> + cb->mr = mr;
> return;
> }
> - if (data->end == memhdr->addr) {
> - data->end += memhdr->len;
> + mr = rte_zmalloc_socket(__func__, sizeof(*mr), 0, mp->socket_id);
> + if (!mr) {
> + DEBUG("unable to allocate MR, pool %p:%u register failed.",
> + (void *)mp, mem_idx);
> + cb->error = -ENOMEM;
> return;
> }
> - if (data->start == (char *)memhdr->addr + memhdr->len) {
> - data->start -= memhdr->len;
> + mr->mr = ibv_reg_mr(priv->pd, memhdr->addr, memhdr->len,
> + IBV_ACCESS_LOCAL_WRITE);
> + if (!mr->mr) {
> + ERROR("unable to register MR, ibv_reg_mr() failed.");
> + cb->error = -1;
> return;
> }
> - /* Error, mempool is not virtually contiguous. */
> - data->ret = -1;
> -}
> -
> -/**
> - * Check if a mempool can be used: it must be virtually contiguous.
> - *
> - * @param[in] mp
> - * Pointer to memory pool.
> - * @param[out] start
> - * Pointer to the start address of the mempool virtual memory area
> - * @param[out] end
> - * Pointer to the end address of the mempool virtual memory area
> - *
> - * @return
> - * 0 on success (mempool is virtually contiguous), -1 on error.
> - */
> -static int mlx5_check_mempool(struct rte_mempool *mp, uintptr_t *start,
> - uintptr_t *end)
> -{
> - struct mlx5_check_mempool_data data;
> -
> - memset(&data, 0, sizeof(data));
> - rte_mempool_mem_iter(mp, mlx5_check_mempool_cb, &data);
> - *start = (uintptr_t)data.start;
> - *end = (uintptr_t)data.end;
> -
> - return data.ret;
> + mr->mp = mp;
> + DEBUG("mempool %p:%u area start=%p size=%zu lkey=0x%08x",
> + (void *)mp, mem_idx, memhdr->addr, memhdr->len, mr->mr->lkey);
> + mr->lkey = rte_cpu_to_be_32(mr->mr->lkey);
> + mr->start = (uintptr_t)memhdr->addr;
> + mr->end = (uintptr_t)mr->mr->addr + mr->mr->length;
> + rte_atomic32_inc(&mr->refcnt);
> + DEBUG("%p: new Memory Region %p refcnt: %d", (void *)priv,
> + (void *)mr, rte_atomic32_read(&mr->refcnt));
> + LIST_INSERT_HEAD(&priv->mr, mr, next);
> + cb->mr = mr;
> }
>
> /**
> - * Register a Memory Region (MR) <-> Memory Pool (MP) association in
> - * txq->mp2mr[]. If mp2mr[] is full, remove an entry first.
> - *
> - * This function should only be called by txq_mp2mr().
> + * Lookup or register a Memory Region (MR).
> *
> * @param priv
> - * Pointer to private structure.
> - * @param txq
> - * Pointer to TX queue structure.
> - * @param[in] mp
> - * Memory Pool for which a Memory Region lkey must be returned.
> - * @param idx
> - * Index of the next available entry.
> + * Pointer to priv structure.
> + * @param mp
> + * Pointer to the memory pool to register.
> + * @param addr
> + * Address to register
> *
> * @return
> * mr on success, NULL on failure.
> */
> struct mlx5_mr*
> -priv_txq_mp2mr_reg(struct priv *priv, struct mlx5_txq_data *txq,
> - struct rte_mempool *mp, unsigned int idx)
> +mlx5_mp2mr(struct priv *priv, struct rte_mempool *mp, uintptr_t addr)
> {
> - struct mlx5_txq_ctrl *txq_ctrl =
> - container_of(txq, struct mlx5_txq_ctrl, txq);
> struct mlx5_mr *mr;
>
> - /* Add a new entry, register MR first. */
> - DEBUG("%p: discovered new memory pool \"%s\" (%p)",
> - (void *)txq_ctrl, mp->name, (void *)mp);
> - mr = priv_mr_get(priv, mp);
> - if (mr == NULL)
> - mr = priv_mr_new(priv, mp);
> - if (unlikely(mr == NULL)) {
> - DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.",
> - (void *)txq_ctrl);
> - return NULL;
> - }
> - if (unlikely(idx == RTE_DIM(txq->mp2mr))) {
> - /* Table is full, remove oldest entry. */
> - DEBUG("%p: MR <-> MP table full, dropping oldest entry.",
> - (void *)txq_ctrl);
> - --idx;
> - priv_mr_release(priv, txq->mp2mr[0]);
> - memmove(&txq->mp2mr[0], &txq->mp2mr[1],
> - (sizeof(txq->mp2mr) - sizeof(txq->mp2mr[0])));
> + priv_lock(priv);
> + mr = priv_mr_lookup(priv, addr);
> + if (!mr) {
> + mr = priv_mr_new(priv, mp, addr);
> + if (mr)
> + rte_atomic32_inc(&mr->refcnt);
> }
> - /* Store the new entry. */
> - txq_ctrl->txq.mp2mr[idx] = mr;
> - DEBUG("%p: new MR lkey for MP \"%s\" (%p): 0x%08" PRIu32,
> - (void *)txq_ctrl, mp->name, (void *)mp,
> - txq_ctrl->txq.mp2mr[idx]->lkey);
> - return mr;
> -}
> -
> -/**
> - * Register a Memory Region (MR) <-> Memory Pool (MP) association in
> - * txq->mp2mr[]. If mp2mr[] is full, remove an entry first.
> - *
> - * This function should only be called by txq_mp2mr().
> - *
> - * @param txq
> - * Pointer to TX queue structure.
> - * @param[in] mp
> - * Memory Pool for which a Memory Region lkey must be returned.
> - * @param idx
> - * Index of the next available entry.
> - *
> - * @return
> - * mr on success, NULL on failure.
> - */
> -struct mlx5_mr*
> -mlx5_txq_mp2mr_reg(struct mlx5_txq_data *txq, struct rte_mempool *mp,
> - unsigned int idx)
> -{
> - struct mlx5_txq_ctrl *txq_ctrl =
> - container_of(txq, struct mlx5_txq_ctrl, txq);
> - struct mlx5_mr *mr;
> -
> - priv_lock(txq_ctrl->priv);
> - mr = priv_txq_mp2mr_reg(txq_ctrl->priv, txq, mp, idx);
> - priv_unlock(txq_ctrl->priv);
> + priv_unlock(priv);
> return mr;
> }
>
> -struct mlx5_mp2mr_mbuf_check_data {
> - int ret;
> -};
> -
> /**
> * Callback function for rte_mempool_obj_iter() to check whether a given
> * mempool object looks like a mbuf.
> @@ -214,10 +145,10 @@ struct mlx5_mp2mr_mbuf_check_data {
> * Object index, unused.
> */
> static void
> -txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj,
> +mp2mr_mbuf_check_cb(struct rte_mempool *mp, void *arg, void *obj,
> uint32_t index __rte_unused)
> {
> - struct mlx5_mp2mr_mbuf_check_data *data = arg;
> + struct mlx5_mempool_cb_data *data = arg;
> struct rte_mbuf *buf = obj;
>
> /*
> @@ -225,7 +156,7 @@ txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj,
> * pointer is valid.
> */
> if (sizeof(*buf) > mp->elt_size || buf->pool != mp)
> - data->ret = -1;
> + data->error = -1;
> }
>
> /**
> @@ -241,21 +172,14 @@ void
> mlx5_mp2mr_iter(struct rte_mempool *mp, void *arg)
> {
> struct priv *priv = (struct priv *)arg;
> - struct mlx5_mp2mr_mbuf_check_data data = {
> - .ret = 0,
> - };
> - struct mlx5_mr *mr;
> + struct mlx5_mempool_cb_data data = {0};
>
> - /* Register mempool only if the first element looks like a mbuf. */
> - if (rte_mempool_obj_iter(mp, txq_mp2mr_mbuf_check, &data) == 0 ||
> - data.ret == -1)
> + /* Register mempool only if all element looks like a mbuf. */
> + /* TODO less efficient to iterate all objects in pool */
> + if (rte_mempool_obj_iter(mp, mp2mr_mbuf_check_cb, &data) == 0 ||
> + data.error == -1)
> return;
What are the performance impact of such lookup with several chunks in
the datapath?
> - mr = priv_mr_get(priv, mp);
> - if (mr) {
> - priv_mr_release(priv, mr);
> - return;
> - }
> - priv_mr_new(priv, mp);
> + priv_mr_new(priv, mp, 0);
> }
>
> /**
> @@ -266,59 +190,30 @@ mlx5_mp2mr_iter(struct rte_mempool *mp, void *arg)
> * Pointer to private structure.
> * @param mp
> * Pointer to the memory pool to register.
> + * @param addr
> + * Address to register
> * @return
> - * The memory region on success.
> + * Registered MR or the last if multiple MR registered.
> */
> -struct mlx5_mr*
> -priv_mr_new(struct priv *priv, struct rte_mempool *mp)
> +struct mlx5_mr *
> +priv_mr_new(struct priv *priv, struct rte_mempool *mp, uintptr_t addr)
> {
> - const struct rte_memseg *ms = rte_eal_get_physmem_layout();
> - uintptr_t start;
> - uintptr_t end;
> - unsigned int i;
> - struct mlx5_mr *mr;
> + struct mlx5_mempool_cb_data cb_data = {
> + .priv = priv,
> + .addr = addr,
> + };
>
> if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> rte_panic("Please init mempool before rte_eth_dev_start() in primary process: %s",
> mp->name);
> - mr = rte_zmalloc_socket(__func__, sizeof(*mr), 0, mp->socket_id);
> - if (!mr) {
> - DEBUG("unable to configure MR, ibv_reg_mr() failed.");
> - return NULL;
> - }
> - if (mlx5_check_mempool(mp, &start, &end) != 0) {
> - ERROR("mempool %p: not virtually contiguous",
> - (void *)mp);
> + DEBUG("%p: discovered new memory pool \"%s\" (%p)",
> + (void *)priv, mp->name, (void *)mp);
> + rte_mempool_mem_iter(mp, mlx5_mempool_register_cb, &cb_data);
> + if (cb_data.error) {
> + DEBUG("%p: unable to configure MR.", (void *)priv);
> return NULL;
> }
> - DEBUG("mempool %p area start=%p end=%p size=%zu",
> - (void *)mp, (void *)start, (void *)end,
> - (size_t)(end - start));
> - /* Round start and end to page boundary if found in memory segments. */
> - for (i = 0; (i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL); ++i) {
> - uintptr_t addr = (uintptr_t)ms[i].addr;
> - size_t len = ms[i].len;
> - unsigned int align = ms[i].hugepage_sz;
> -
> - if ((start > addr) && (start < addr + len))
> - start = RTE_ALIGN_FLOOR(start, align);
> - if ((end > addr) && (end < addr + len))
> - end = RTE_ALIGN_CEIL(end, align);
> - }
> - DEBUG("mempool %p using start=%p end=%p size=%zu for MR",
> - (void *)mp, (void *)start, (void *)end,
> - (size_t)(end - start));
> - mr->mr = ibv_reg_mr(priv->pd, (void *)start, end - start,
> - IBV_ACCESS_LOCAL_WRITE);
> - mr->mp = mp;
> - mr->lkey = rte_cpu_to_be_32(mr->mr->lkey);
> - mr->start = start;
> - mr->end = (uintptr_t)mr->mr->addr + mr->mr->length;
> - rte_atomic32_inc(&mr->refcnt);
> - DEBUG("%p: new Memory Region %p refcnt: %d", (void *)priv,
> - (void *)mr, rte_atomic32_read(&mr->refcnt));
> - LIST_INSERT_HEAD(&priv->mr, mr, next);
> - return mr;
> + return cb_data.mr;
> }
>
> /**
> @@ -396,3 +291,26 @@ priv_mr_verify(struct priv *priv)
> }
> return ret;
> }
> +
> +/**
> + * Memory Region (MR) lookup by address
> + *
> + * @param priv
> + * Pointer to priv structure.
> + * @param[in] addr
> + * Address to lookup.
> + * @return
> + * mr on success, (uint32_t)-1 on failure.
> + */
> +struct mlx5_mr *
> +priv_mr_lookup(struct priv *priv, uintptr_t addr)
> +{
> + struct mlx5_mr *mr;
> +
> + LIST_FOREACH(mr, &priv->mr, next) {
> + if (addr >= mr->start && addr <= mr->end)
> + return mr;
> + }
> + return NULL;
> +}
> +
> diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c
> index 950472754..a581a2d61 100644
> --- a/drivers/net/mlx5/mlx5_rxq.c
> +++ b/drivers/net/mlx5/mlx5_rxq.c
> @@ -652,6 +652,7 @@ mlx5_priv_rxq_ibv_new(struct priv *priv, uint16_t idx)
> int ret = 0;
> struct mlx5dv_obj obj;
> struct mlx5_dev_config *config = &priv->config;
> + struct mlx5_mr *last_mr = NULL;
>
> assert(rxq_data);
> assert(!rxq_ctrl->ibv);
> @@ -664,13 +665,9 @@ mlx5_priv_rxq_ibv_new(struct priv *priv, uint16_t idx)
> }
> tmpl->rxq_ctrl = rxq_ctrl;
> /* Use the entire RX mempool as the memory region. */
> - tmpl->mr = priv_mr_get(priv, rxq_data->mp);
> - if (!tmpl->mr) {
> - tmpl->mr = priv_mr_new(priv, rxq_data->mp);
> - if (!tmpl->mr) {
> - ERROR("%p: MR creation failure", (void *)rxq_ctrl);
> - goto error;
> - }
> + if (!priv_mr_new(priv, rxq_data->mp, 0)) {
> + ERROR("%p: MR creation failure", (void *)rxq_ctrl);
> + goto error;
> }
> if (rxq_ctrl->irq) {
> tmpl->channel = ibv_create_comp_channel(priv->ctx);
> @@ -786,14 +783,17 @@ mlx5_priv_rxq_ibv_new(struct priv *priv, uint16_t idx)
> for (i = 0; (i != (unsigned int)(1 << rxq_data->elts_n)); ++i) {
> struct rte_mbuf *buf = (*rxq_data->elts)[i];
> volatile struct mlx5_wqe_data_seg *scat = &(*rxq_data->wqes)[i];
> + uintptr_t addr = rte_pktmbuf_mtod(buf, uintptr_t);
>
> + if (!last_mr || addr < last_mr->start || addr > last_mr->end)
> + last_mr = priv_mr_lookup(priv, addr);
> + assert(last_mr);
> /* scat->addr must be able to store a pointer. */
> assert(sizeof(scat->addr) >= sizeof(uintptr_t));
> *scat = (struct mlx5_wqe_data_seg){
> - .addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(buf,
> - uintptr_t)),
> + .addr = rte_cpu_to_be_64(addr),
> .byte_count = rte_cpu_to_be_32(DATA_LEN(buf)),
> - .lkey = tmpl->mr->lkey,
> + .lkey = last_mr->lkey,
> };
> }
> rxq_data->rq_db = rwq.dbrec;
> @@ -826,8 +826,6 @@ mlx5_priv_rxq_ibv_new(struct priv *priv, uint16_t idx)
> claim_zero(ibv_destroy_cq(tmpl->cq));
> if (tmpl->channel)
> claim_zero(ibv_destroy_comp_channel(tmpl->channel));
> - if (tmpl->mr)
> - priv_mr_release(priv, tmpl->mr);
> return NULL;
> }
>
> @@ -877,17 +875,12 @@ mlx5_priv_rxq_ibv_get(struct priv *priv, uint16_t idx)
> int
> mlx5_priv_rxq_ibv_release(struct priv *priv, struct mlx5_rxq_ibv *rxq_ibv)
> {
> - int ret;
> -
> assert(rxq_ibv);
> assert(rxq_ibv->wq);
> assert(rxq_ibv->cq);
> - assert(rxq_ibv->mr);
> - ret = priv_mr_release(priv, rxq_ibv->mr);
> - if (!ret)
> - rxq_ibv->mr = NULL;
> DEBUG("%p: Verbs Rx queue %p: refcnt %d", (void *)priv,
> (void *)rxq_ibv, rte_atomic32_read(&rxq_ibv->refcnt));
> + (void)priv;
> if (rte_atomic32_dec_and_test(&rxq_ibv->refcnt)) {
> rxq_free_elts(rxq_ibv->rxq_ctrl);
> claim_zero(ibv_destroy_wq(rxq_ibv->wq));
> diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
> index 18e1d26f3..6589a662e 100644
> --- a/drivers/net/mlx5/mlx5_rxtx.h
> +++ b/drivers/net/mlx5/mlx5_rxtx.h
> @@ -142,7 +142,6 @@ struct mlx5_rxq_ibv {
> struct ibv_cq *cq; /* Completion Queue. */
> struct ibv_wq *wq; /* Work Queue. */
> struct ibv_comp_channel *channel;
> - struct mlx5_mr *mr; /* Memory Region (for mp). */
> };
>
> /* RX queue control descriptor. */
> @@ -324,10 +323,8 @@ uint16_t mlx5_rx_burst_vec(void *, struct rte_mbuf **, uint16_t);
> /* mlx5_mr.c */
>
> void mlx5_mp2mr_iter(struct rte_mempool *, void *);
> -struct mlx5_mr *priv_txq_mp2mr_reg(struct priv *priv, struct mlx5_txq_data *,
> - struct rte_mempool *, unsigned int);
> -struct mlx5_mr *mlx5_txq_mp2mr_reg(struct mlx5_txq_data *, struct rte_mempool *,
> - unsigned int);
> +struct mlx5_mr *mlx5_mp2mr(struct priv *priv, struct rte_mempool *mp,
> + uintptr_t addr);
>
> #ifndef NDEBUG
> /**
> @@ -523,7 +520,7 @@ mlx5_tx_complete(struct mlx5_txq_data *txq)
> * @return
> * Memory pool where data is located for given mbuf.
> */
> -static struct rte_mempool *
> +static __rte_always_inline struct rte_mempool *
> mlx5_tx_mb2mp(struct rte_mbuf *buf)
> {
> if (unlikely(RTE_MBUF_INDIRECT(buf)))
> @@ -552,30 +549,41 @@ mlx5_tx_mb2mr(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
> struct mlx5_mr *mr;
>
> assert(i < RTE_DIM(txq->mp2mr));
> - if (likely(txq->mp2mr[i]->start <= addr && txq->mp2mr[i]->end >= addr))
> + if (likely(txq->mp2mr[i] && txq->mp2mr[i]->start <= addr &&
> + txq->mp2mr[i]->end >= addr))
> return txq->mp2mr[i]->lkey;
> for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
> - if (unlikely(txq->mp2mr[i]->mr == NULL)) {
> - /* Unknown MP, add a new MR for it. */
> + if (txq->mp2mr[i] == NULL)
> break;
> - }
> + if (i == txq->mr_cache_idx)
> + continue;
> if (txq->mp2mr[i]->start <= addr &&
> txq->mp2mr[i]->end >= addr) {
> +#ifndef NDEBUG
> + if (rte_eal_process_type() == RTE_PROC_PRIMARY)
> + assert(rte_cpu_to_be_32(txq->mp2mr[i]->mr->lkey)
> + == txq->mp2mr[i]->lkey);
> +#endif
> txq->mr_cache_idx = i;
> return txq->mp2mr[i]->lkey;
> }
> }
> - txq->mr_cache_idx = 0;
> - mr = mlx5_txq_mp2mr_reg(txq, mlx5_tx_mb2mp(mb), i);
> - /*
> - * Request the reference to use in this queue, the original one is
> - * kept by the control plane.
> - */
> - if (mr) {
> - rte_atomic32_inc(&mr->refcnt);
> - return mr->lkey;
> + mr = mlx5_mp2mr(container_of(txq, struct mlx5_txq_ctrl, txq)->priv,
> + mlx5_tx_mb2mp(mb), addr);
> + assert(mr);
> + /* recent used MR first */
> + if (i) {
> + if (i >= RTE_DIM(txq->mp2mr)) {
> + i = RTE_DIM(txq->mp2mr) - 1;
> + DEBUG("TXQ MR cache full, please consider increasing CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE in config file");
Please respect the coding style of the PMD/file split those lines.
> + }
> + memmove(&txq->mp2mr[1], &txq->mp2mr[0],
> + i * sizeof(sizeof(txq->mp2mr[0])));
> }
> - return (uint32_t)-1;
> + /* Store the new entry. */
> + txq->mp2mr[0] = mr;
> + txq->mr_cache_idx = 0;
> + return mr ? mr->lkey : (uint32_t)-1;
> }
>
> /**
> diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
> index 1a20967a2..920cc0f46 100644
> --- a/drivers/net/mlx5/mlx5_trigger.c
> +++ b/drivers/net/mlx5/mlx5_trigger.c
> @@ -58,17 +58,10 @@ priv_txq_start(struct priv *priv)
>
> /* Add memory regions to Tx queues. */
> for (i = 0; i != priv->txqs_n; ++i) {
> - unsigned int idx = 0;
> - struct mlx5_mr *mr;
> struct mlx5_txq_ctrl *txq_ctrl = mlx5_priv_txq_get(priv, i);
>
> if (!txq_ctrl)
> continue;
> - LIST_FOREACH(mr, &priv->mr, next) {
> - priv_txq_mp2mr_reg(priv, &txq_ctrl->txq, mr->mp, idx++);
> - if (idx == MLX5_PMD_TX_MP_CACHE)
> - break;
> - }
> txq_alloc_elts(txq_ctrl);
> txq_ctrl->ibv = mlx5_priv_txq_ibv_new(priv, i);
> if (!txq_ctrl->ibv) {
> --
> 2.13.3
>
Thanks,
--
Nélio Laranjeiro
6WIND
next prev parent reply other threads:[~2018-01-15 16:28 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-15 6:54 [dpdk-dev] [PATCH 1/4] net/mlx5: revert "fix Memory Region registration" Xueming Li
2018-01-15 6:54 ` [dpdk-dev] [PATCH 2/4] net/mlx5: forbid MR registration in secondary process Xueming Li
2018-01-15 15:33 ` Nélio Laranjeiro
2018-01-15 6:54 ` [dpdk-dev] [PATCH 3/4] net/mlx5: support mempool of multi-mem segments Xueming Li
2018-01-15 16:29 ` Nélio Laranjeiro [this message]
2018-01-15 6:54 ` [dpdk-dev] [PATCH 4/4] net/mlx5: remove MR refcnt Xueming Li
2018-01-16 8:09 ` Nélio Laranjeiro
2018-01-15 15:26 ` [dpdk-dev] [PATCH 1/4] net/mlx5: revert "fix Memory Region registration" Nélio Laranjeiro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180115162946.hu7mtcruyb66ke7d@shalom \
--to=nelio.laranjeiro@6wind.com \
--cc=dev@dpdk.org \
--cc=shahafs@mellanox.com \
--cc=xuemingl@mellanox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).