Skip to content

Commit

Permalink
IB/mlx5: Refactor UMR to have its own context struct
Browse files Browse the repository at this point in the history
Instead of having the UMR context part of each memory region, allocate
a struct on the stack.  This allows queuing multiple UMRs that access
the same memory region.

Signed-off-by: Shachar Raindel <raindel@mellanox.com>
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Shachar Raindel authored and Roland Dreier committed May 27, 2014
1 parent 48fea83 commit a74d241
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 22 deletions.
13 changes: 11 additions & 2 deletions drivers/infiniband/hw/mlx5/mlx5_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,6 @@ struct mlx5_ib_mr {
__be64 *pas;
dma_addr_t dma;
int npages;
struct completion done;
enum ib_wc_status status;
struct mlx5_ib_dev *dev;
struct mlx5_create_mkey_mbox_out out;
struct mlx5_core_sig_ctx *sig;
Expand All @@ -277,6 +275,17 @@ struct mlx5_ib_fast_reg_page_list {
dma_addr_t map;
};

struct mlx5_ib_umr_context {
enum ib_wc_status status;
struct completion done;
};

static inline void mlx5_ib_init_umr_context(struct mlx5_ib_umr_context *context)
{
context->status = -1;
init_completion(&context->done);
}

struct umr_common {
struct ib_pd *pd;
struct ib_cq *cq;
Expand Down
40 changes: 20 additions & 20 deletions drivers/infiniband/hw/mlx5/mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev,

void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context)
{
struct mlx5_ib_mr *mr;
struct mlx5_ib_umr_context *context;
struct ib_wc wc;
int err;

Expand All @@ -721,9 +721,9 @@ void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context)
if (err == 0)
break;

mr = (struct mlx5_ib_mr *)(unsigned long)wc.wr_id;
mr->status = wc.status;
complete(&mr->done);
context = (struct mlx5_ib_umr_context *)wc.wr_id;
context->status = wc.status;
complete(&context->done);
}
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
}
Expand All @@ -735,6 +735,7 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
struct mlx5_ib_dev *dev = to_mdev(pd->device);
struct device *ddev = dev->ib_dev.dma_device;
struct umr_common *umrc = &dev->umrc;
struct mlx5_ib_umr_context umr_context;
struct ib_send_wr wr, *bad;
struct mlx5_ib_mr *mr;
struct ib_sge sg;
Expand Down Expand Up @@ -774,24 +775,21 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
}

memset(&wr, 0, sizeof(wr));
wr.wr_id = (u64)(unsigned long)mr;
wr.wr_id = (u64)(unsigned long)&umr_context;
prep_umr_reg_wqe(pd, &wr, &sg, mr->dma, npages, mr->mmr.key, page_shift, virt_addr, len, access_flags);

/* We serialize polls so one process does not kidnap another's
* completion. This is not a problem since wr is completed in
* around 1 usec
*/
mlx5_ib_init_umr_context(&umr_context);
down(&umrc->sem);
init_completion(&mr->done);
err = ib_post_send(umrc->qp, &wr, &bad);
if (err) {
mlx5_ib_warn(dev, "post send failed, err %d\n", err);
goto unmap_dma;
}
wait_for_completion(&mr->done);
if (mr->status != IB_WC_SUCCESS) {
mlx5_ib_warn(dev, "reg umr failed\n");
err = -EFAULT;
} else {
wait_for_completion(&umr_context.done);
if (umr_context.status != IB_WC_SUCCESS) {
mlx5_ib_warn(dev, "reg umr failed\n");
err = -EFAULT;
}
}

mr->mmr.iova = virt_addr;
Expand Down Expand Up @@ -940,24 +938,26 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
{
struct umr_common *umrc = &dev->umrc;
struct mlx5_ib_umr_context umr_context;
struct ib_send_wr wr, *bad;
int err;

memset(&wr, 0, sizeof(wr));
wr.wr_id = (u64)(unsigned long)mr;
wr.wr_id = (u64)(unsigned long)&umr_context;
prep_umr_unreg_wqe(dev, &wr, mr->mmr.key);

mlx5_ib_init_umr_context(&umr_context);
down(&umrc->sem);
init_completion(&mr->done);
err = ib_post_send(umrc->qp, &wr, &bad);
if (err) {
up(&umrc->sem);
mlx5_ib_dbg(dev, "err %d\n", err);
goto error;
} else {
wait_for_completion(&umr_context.done);
up(&umrc->sem);
}
wait_for_completion(&mr->done);
up(&umrc->sem);
if (mr->status != IB_WC_SUCCESS) {
if (umr_context.status != IB_WC_SUCCESS) {
mlx5_ib_warn(dev, "unreg umr failed\n");
err = -EFAULT;
goto error;
Expand Down

0 comments on commit a74d241

Please sign in to comment.